1 import { TypedTESIDCoder, TESIDCoder } from "./tesid.js";
3 function assert_eq(a: any, b: any, msg?: string) {
4 if ((a == null ? a : a.toString()) !== (b == null ? b : b.toString())) {
6 "assert_eq failed" + (msg ? ": " + msg : "") +
13 function assert_ne(a: any, b: any, msg?: string) {
14 if ((a == null ? a : a.toString()) === (b == null ? b : b.toString())) {
16 "assert_ne failed" + (msg ? ": " + msg : "") +
23 function assert_throws(f: () => any, msg_or_type: string | typeof Error) {
28 if (msg_or_type != null) {
29 if (typeof msg_or_type == "string") {
30 if (e.toString() != msg_or_type) {
31 throw new Error("Expected exception `" + msg_or_type + "`, but found exception `" + e.toString() + "`");
34 if (!(e instanceof msg_or_type)) {
35 throw new Error("Expected exception of type " + msg_or_type.name + ", but found exception `" + e.toString() + "`");
41 throw new Error("Expected exception " +
42 (msg_or_type == null ? "" :
43 typeof msg_or_type == "string" ? "`" + msg_or_type + "`" :
44 "of type " + msg_or_type.name) +
45 "\nCode did not fail, but returned " + (x == null ? x : x.toString()));
48 // First with a true TypeScript enum
55 const coder = new TypedTESIDCoder(new TESIDCoder("000102030405060708090a0b0c0d0e0f"), 256n, Type);
57 assert_eq(coder.encode(Type.A, 0n), "w2ej");
58 assert_eq(coder.encode(Type.B, 0n), "w6um");
59 assert_eq(coder.encode(Type.A, 1n), "dh2h");
60 assert_eq(coder.encode(0, 1n), "dh2h");
61 assert_eq(coder.encode(3, 1n), "r6wb"); // Unfortunately accepted by TypeScript; and deliberately permitted by our code.
62 // @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'Type'.
63 assert_throws(() => coder.encode(Type[Type.A], 1n), SyntaxError); // “Cannot convert A to a BigInt” or similar. (SyntaxError instead of TypeError is acceptable to me.)
64 enum WrongType { A = 0, B = 1, C = 2 }
65 // @ts-expect-error TS2345: Argument of type 'WrongType.A' is not assignable to parameter of type 'Type'.
66 coder.encode(WrongType.A, 0n);
68 assert_eq(coder.decode(Type.A, "w2ej"), 0n);
69 assert_eq(coder.decode(Type.B, "w6um"), 0n);
70 assert_eq(coder.decode(Type.A, "dh2h"), 1n);
71 assert_eq(coder.decode(3, "r6wb"), 1n);
72 assert_throws(() => coder.decode(Type.A, "w5um"), RangeError);
73 // … but although encode and decode *accepted* an invalid variant, splitDecode mustn’t *produce* an invalid variant.
74 assert_throws(() => coder.splitDecode("r6wb"), "RangeError: bad TESID");
75 let sd = coder.splitDecode("w6um");
76 // (Doing *strict* equality checking this time.)
77 assert_eq(sd.id === 0n, true);
78 assert_eq(sd.discriminant === Type.B, true);
81 // With a JavaScript-style enum
91 const coder = new TypedTESIDCoder(new TESIDCoder("000102030405060708090a0b0c0d0e0f"), 256n, Type);
93 assert_eq(coder.encode(Type.A, 0n), "w2ej");
94 assert_eq(coder.encode(Type.B, 0n), "w6um");
95 assert_eq(coder.encode(Type.A, 1n), "dh2h");
96 assert_eq(coder.encode(0, 1n), "dh2h");
97 assert_eq(coder.encode(3, 1n), "r6wb"); // Unfortunately accepted by TypeScript; and deliberately permitted by our code.
98 // Note no compile-time TS2345 error this time—it resolves to string | number. Pity, but can’t really do better.
99 assert_throws(() => coder.encode(Type[Type.A], 1n), SyntaxError); // “Cannot convert A to a BigInt” or similar. (SyntaxError instead of TypeError is acceptable to me.)
101 assert_eq(coder.decode(Type.A, "w2ej"), 0n);
102 assert_eq(coder.decode(Type.B, "w6um"), 0n);
103 assert_eq(coder.decode(Type.A, "dh2h"), 1n);
104 assert_eq(coder.decode(3, "r6wb"), 1n);
105 assert_throws(() => coder.decode(Type.A, "w5um"), RangeError);
106 // … but although encode and decode *accepted* an invalid variant, splitDecode mustn’t *produce* an invalid variant.
107 assert_throws(() => coder.splitDecode("r6wb"), "RangeError: bad TESID");