X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/3d2a5e40eaf384aee6b9699bc71af015fd2cb2e9..6e6d4e3261c1c943fe44fa9e381bcf8bf1441fd6:/binary.test.js diff --git a/binary.test.js b/binary.test.js index 161f8db..82fa4e0 100755 --- a/binary.test.js +++ b/binary.test.js @@ -1,7 +1,7 @@ // ♓🌟 Piscēs ∷ binary.test.js // ==================================================================== // -// Copyright © 2020–2022 Lady [@ Lady’s Computer]. +// Copyright © 2020–2023 Lady [@ Lady’s Computer]. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -16,50 +16,447 @@ import { it, } from "./dev-deps.js"; import { + base16Binary, + base16String, + base32Binary, + base32String, base64Binary, base64String, filenameSafeBase64Binary, filenameSafeBase64String, + isBase16, + isBase32, isBase64, isFilenameSafeBase64, + isWRMGBase32, + wrmgBase32Binary, + wrmgBase32String, } from "./binary.js"; -const base64s = { - "AGIAYQBzAGUANgA0": "base64", - "R/Q=": new Uint16Array([62535]), - "S0lCSQ==": new Uint8ClampedArray([75, 73, 66, 73]).buffer, - YmFzZTY0: new DataView( - new Uint8Array([98, 97, 115, 101, 54, 52]).buffer, - ), -}; +// These tests assume a LITTLE‐ENDIAN environment. +const data = new Map([ + ["", { + base16: "", + base32: "", + base64: "", + wrmg: "", + }], + ["base64", { + base16: "006200610073006500360034", + base32: "ABRAAYIAOMAGKABWAA2A====", + base64: "AGIAYQBzAGUANgA0", + wrmg: "01H00R80EC06A01P00T0", + }], + [new Uint16Array([62535]), { + base16: "47F4", + base32: "I72A====", + base64: "R/Q=", + wrmg: "8ZT0", + }], + [new Uint8ClampedArray([75, 73, 66, 73]).buffer, { + base16: "4B494249", + base32: "JNEUESI=", + base64: "S0lCSQ==", + wrmg: "9D4M4J8", + }], + [new DataView(new Uint8Array([98, 97, 115, 101, 54, 52]).buffer), { + base16: "626173653634", + base32: "MJQXGZJWGQ======", + base64: "YmFzZTY0", + wrmg: "C9GQ6S9P6G", + }], + + // The following three examples are from RFC 3548. + [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), { + base16: "14FB9C03D97E", + base32: "CT5ZYA6ZPY======", + base64: "FPucA9l+", + wrmg: "2KXSR0YSFR", + }], + [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), { + base16: "14FB9C03D9", + base32: "CT5ZYA6Z", + base64: "FPucA9k=", + wrmg: "2KXSR0YS", + }], + [new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), { + base16: "14FB9C03", + base32: "CT5ZYAY=", + base64: "FPucAw==", + wrmg: "2KXSR0R", + }], + + // The following examples are from the Ruby base32 gem. + [new Uint8Array([0x28]), { + base16: "28", + base32: "FA======", + base64: "KA==", + wrmg: "50", + }], + [new Uint8Array([0xD6]), { + base16: "D6", + base32: "2Y======", + base64: "1g==", + wrmg: "TR", + }], + [new Uint16Array([0xF8D6]), { + base16: "D6F8", + base32: "234A====", + base64: "1vg=", + wrmg: "TVW0", + }], + [new Uint8Array([0xD6, 0xF8, 0x00]), { + base16: "D6F800", + base32: "234AA===", + base64: "1vgA", + wrmg: "TVW00", + }], + [new Uint8Array([0xD6, 0xF8, 0x10]), { + base16: "D6F810", + base32: "234BA===", + base64: "1vgQ", + wrmg: "TVW10", + }], + [new Uint32Array([0x0C11F8D6]), { + base16: "D6F8110C", + base32: "234BCDA=", + base64: "1vgRDA==", + wrmg: "TVW1230", + }], + [new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), { + base16: "D6F8110C80", + base32: "234BCDEA", + base64: "1vgRDIA=", + wrmg: "TVW12340", + }], + [new Uint16Array([0xF8D6, 0x0C11, 0x3085]), { + base16: "D6F8110C8530", + base32: "234BCDEFGA======", + base64: "1vgRDIUw", + wrmg: "TVW1234560", + }], +]); + +describe("base16Binary", () => { + it("[[Call]] returns the correct data", () => { + assertEquals( + new Uint8Array(base16Binary("")), + new Uint8Array([]), + "", + ); + assertEquals( + new Uint8Array(base16Binary("006200610073006500360034")), + Uint8Array.from( + "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", + ($) => $.charCodeAt(0), + ), + "006200610073006500360034", + ); + assertEquals( + new Uint16Array(base16Binary("47F4")), + new Uint16Array([62535]), + "47F4", + ); + assertEquals( + new Uint8ClampedArray(base16Binary("4B494249")), + new Uint8ClampedArray([75, 73, 66, 73]), + "4B494249", + ); + assertEquals( + new Uint8Array(base16Binary("626173653634")), + new Uint8Array([98, 97, 115, 101, 54, 52]), + "626173653634", + ); + assertEquals( + new Uint8Array(base16Binary("14FB9C03D97E")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), + "14FB9C03D97E", + ); + assertEquals( + new Uint8Array(base16Binary("14FB9C03D9")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), + "14FB9C03D9", + ); + assertEquals( + new Uint8Array(base16Binary("14FB9C03")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), + "14FB9C03", + ); + assertEquals( + new Uint8Array(base16Binary("28")), + new Uint8Array([0x28]), + "28", + ); + assertEquals( + new Uint8Array(base16Binary("D6")), + new Uint8Array([0xD6]), + "D6", + ); + assertEquals( + new Uint16Array(base16Binary("D6F8")), + new Uint16Array([0xF8D6]), + "D6F8", + ); + assertEquals( + new Uint8Array(base16Binary("D6F800")), + new Uint8Array([0xD6, 0xF8, 0x00]), + "D6F800", + ); + assertEquals( + new Uint8Array(base16Binary("D6F810")), + new Uint8Array([0xD6, 0xF8, 0x10]), + "D6F810", + ); + assertEquals( + new Uint32Array(base16Binary("D6F8110C")), + new Uint32Array([0x0C11F8D6]), + "D6F8110C", + ); + assertEquals( + new Uint8Array(base16Binary("D6F8110C80")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "D6F8110C80", + ); + assertEquals( + new Uint16Array(base16Binary("D6F8110C8530")), + new Uint16Array([0xF8D6, 0x0C11, 0x3085]), + "D6F8110C8530", + ); + }); + + it("[[Call]] is case‐insensitive", () => { + assertEquals( + new Uint8Array(base16Binary("d6f8110C80")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "d6f8110C80", + ); + }); + + it("[[Call]] throws when provided with an invalid character", () => { + assertThrows(() => base16Binary("ABCG")); + }); + + it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 2", () => { + assertThrows(() => base16Binary("A")); + assertThrows(() => base16Binary("ABC")); + }); +}); + +describe("base16String", () => { + it("[[Call]] returns the correct string", () => { + for (const [source, { base16 }] of data) { + assertStrictEquals(base16String(source), base16); + } + }); +}); + +describe("base32Binary", () => { + it("[[Call]] returns the correct data", () => { + assertEquals( + new Uint8Array(base32Binary("")), + new Uint8Array([]), + "", + ); + assertEquals( + new Uint8Array(base32Binary("ABRAAYIAOMAGKABWAA2A====")), + Uint8Array.from( + "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", + ($) => $.charCodeAt(0), + ), + "ABRAAYIAOMAGKABWAA2A====", + ); + assertEquals( + new Uint16Array(base32Binary("I72A====")), + new Uint16Array([62535]), + "I72A====", + ); + assertEquals( + new Uint8ClampedArray(base32Binary("JNEUESI=")), + new Uint8ClampedArray([75, 73, 66, 73]), + "JNEUESI=", + ); + assertEquals( + new Uint8Array(base32Binary("MJQXGZJWGQ======")), + new Uint8Array([98, 97, 115, 101, 54, 52]), + "MJQXGZJWGQ======", + ); + assertEquals( + new Uint8Array(base32Binary("CT5ZYA6ZPY======")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), + "CT5ZYA6ZPY======", + ); + assertEquals( + new Uint8Array(base32Binary("CT5ZYA6Z")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), + "CT5ZYA6Z", + ); + assertEquals( + new Uint8Array(base32Binary("CT5ZYAY=")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), + "CT5ZYAY=", + ); + assertEquals( + new Uint8Array(base32Binary("FA======")), + new Uint8Array([0x28]), + "FA======", + ); + assertEquals( + new Uint8Array(base32Binary("2Y======")), + new Uint8Array([0xD6]), + "2Y======", + ); + assertEquals( + new Uint16Array(base32Binary("234A====")), + new Uint16Array([0xF8D6]), + "234A====", + ); + assertEquals( + new Uint8Array(base32Binary("234AA===")), + new Uint8Array([0xD6, 0xF8, 0x00]), + "234AA===", + ); + assertEquals( + new Uint8Array(base32Binary("234BA===")), + new Uint8Array([0xD6, 0xF8, 0x10]), + "234BA===", + ); + assertEquals( + new Uint32Array(base32Binary("234BCDA=")), + new Uint32Array([0x0C11F8D6]), + "234BCDA=", + ); + assertEquals( + new Uint8Array(base32Binary("234BCDEA")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "234BCDEA", + ); + assertEquals( + new Uint16Array(base32Binary("234BCDEFGA======")), + new Uint16Array([0xF8D6, 0x0C11, 0x3085]), + "234BCDEFGA======", + ); + }); + + it("[[Call]] is case‐insensitive", () => { + assertEquals( + new Uint8Array(base32Binary("234bcdEA")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "234bcdEA", + ); + }); + + it("[[Call]] throws when provided with an invalid character", () => { + assertThrows(() => base32Binary("ABC0")); + assertThrows(() => base32Binary("ABC1")); + assertThrows(() => base32Binary("ABC8")); + assertThrows(() => base32Binary("ABC9")); + }); + + it("[[Call]] throws when provided with an invalid equals", () => { + assertThrows(() => base32Binary("CT3ZYAY==")); + }); + + it("[[Call]] throws when provided with a length with a remainder of 1, 3 ∣ 6 when divided by 8", () => { + assertThrows(() => base32Binary("234BCDEAA")); + assertThrows(() => base32Binary("234BCDEAA=======")); + assertThrows(() => base32Binary("UHI")); + assertThrows(() => base32Binary("UHIUJD")); + }); +}); + +describe("base32String", () => { + it("[[Call]] returns the correct string", () => { + for (const [source, { base32 }] of data) { + assertStrictEquals(base32String(source), base32); + } + }); +}); describe("base64Binary", () => { it("[[Call]] returns the correct data", () => { assertEquals( - base64Binary("AGIAYQBzAGUANgA0"), - new Uint8Array( - Array.prototype.map.call( - "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", - ($) => $.charCodeAt(0), - ), - ).buffer, + new Uint8Array(base64Binary("")), + new Uint8Array([]), + "", + ); + assertEquals( + new Uint8Array(base64Binary("AGIAYQBzAGUANgA0")), + Uint8Array.from( + "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", + ($) => $.charCodeAt(0), + ), "AGIAYQBzAGUANgA0", ); assertEquals( - base64Binary("R/Q="), - new Uint16Array([62535]).buffer, + new Uint16Array(base64Binary("R/Q=")), + new Uint16Array([62535]), "R/Q=", ); assertEquals( - base64Binary("S0lCSQ=="), - new Uint8ClampedArray([75, 73, 66, 73]).buffer, + new Uint8ClampedArray(base64Binary("S0lCSQ==")), + new Uint8ClampedArray([75, 73, 66, 73]), "S0lCSQ==", ); assertEquals( - base64Binary("YmFzZTY0"), - new Uint8Array([98, 97, 115, 101, 54, 52]).buffer, + new Uint8Array(base64Binary("YmFzZTY0")), + new Uint8Array([98, 97, 115, 101, 54, 52]), "YmFzZTY0", ); + assertEquals( + new Uint8Array(base64Binary("FPucA9l+")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), + "FPucA9l+", + ); + assertEquals( + new Uint8Array(base64Binary("FPucA9k=")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), + "FPucA9k=", + ); + assertEquals( + new Uint8Array(base64Binary("FPucAw==")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), + "FPucAw==", + ); + assertEquals( + new Uint8Array(base64Binary("KA==")), + new Uint8Array([0x28]), + "KA==", + ); + assertEquals( + new Uint8Array(base64Binary("1g==")), + new Uint8Array([0xD6]), + "1g==", + ); + assertEquals( + new Uint16Array(base64Binary("1vg")), + new Uint16Array([0xF8D6]), + "1vg", + ); + assertEquals( + new Uint8Array(base64Binary("1vgA")), + new Uint8Array([0xD6, 0xF8, 0x00]), + "1vgA", + ); + assertEquals( + new Uint8Array(base64Binary("1vgQ")), + new Uint8Array([0xD6, 0xF8, 0x10]), + "1vgQ", + ); + assertEquals( + new Uint32Array(base64Binary("1vgRDA==")), + new Uint32Array([0x0C11F8D6]), + "1vgRDA==", + ); + assertEquals( + new Uint8Array(base64Binary("1vgRDIA=")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "1vgRDIA=", + ); + assertEquals( + new Uint16Array(base64Binary("1vgRDIUw")), + new Uint16Array([0xF8D6, 0x0C11, 0x3085]), + "1vgRDIUw", + ); }); it("[[Call]] throws when provided with an invalid character", () => { @@ -78,39 +475,82 @@ describe("base64Binary", () => { describe("base64String", () => { it("[[Call]] returns the correct string", () => { - Object.entries(base64s).forEach(([key, value]) => - assertStrictEquals(base64String(value), key) - ); + for (const [source, { base64 }] of data) { + assertStrictEquals(base64String(source), base64); + } }); }); describe("filenameSafeBase64Binary", () => { it("[[Call]] returns the correct data", () => { assertEquals( - filenameSafeBase64Binary("AGIAYQBzAGUANgA0"), - new Uint8Array( - Array.prototype.map.call( - "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", - ($) => $.charCodeAt(0), - ), - ).buffer, + new Uint8Array(filenameSafeBase64Binary("")), + new Uint8Array([]), + "", + ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("AGIAYQBzAGUANgA0")), + Uint8Array.from( + "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", + ($) => $.charCodeAt(0), + ), "AGIAYQBzAGUANgA0", ); assertEquals( - filenameSafeBase64Binary("R_Q="), - new Uint16Array([62535]).buffer, + new Uint16Array(filenameSafeBase64Binary("R_Q=")), + new Uint16Array([62535]), "R/Q=", ); assertEquals( - filenameSafeBase64Binary("S0lCSQ=="), - new Uint8ClampedArray([75, 73, 66, 73]).buffer, + new Uint8ClampedArray(filenameSafeBase64Binary("S0lCSQ==")), + new Uint8ClampedArray([75, 73, 66, 73]), "S0lCSQ==", ); assertEquals( - filenameSafeBase64Binary("YmFzZTY0"), - new Uint8Array([98, 97, 115, 101, 54, 52]).buffer, + new Uint8Array(filenameSafeBase64Binary("YmFzZTY0")), + new Uint8Array([98, 97, 115, 101, 54, 52]), "YmFzZTY0", ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("KA==")), + new Uint8Array([0x28]), + "KA==", + ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("1g==")), + new Uint8Array([0xD6]), + "1g==", + ); + assertEquals( + new Uint16Array(filenameSafeBase64Binary("1vg")), + new Uint16Array([0xF8D6]), + "1vg", + ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("1vgA")), + new Uint8Array([0xD6, 0xF8, 0x00]), + "1vgA", + ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("1vgQ")), + new Uint8Array([0xD6, 0xF8, 0x10]), + "1vgQ", + ); + assertEquals( + new Uint32Array(filenameSafeBase64Binary("1vgQDA==")), + new Uint32Array([0x0C10F8D6]), + "1vgQDA==", + ); + assertEquals( + new Uint8Array(filenameSafeBase64Binary("1vgQDIA=")), + new Uint8Array([0xD6, 0xF8, 0x10, 0x0C, 0x80]), + "1vgQDIA=", + ); + assertEquals( + new Uint16Array(filenameSafeBase64Binary("1vgQDIUw")), + new Uint16Array([0xF8D6, 0x0C10, 0x3085]), + "1vgQDIUw", + ); }); it("[[Call]] throws when provided with an invalid character", () => { @@ -129,18 +569,75 @@ describe("filenameSafeBase64Binary", () => { describe("filenameSafeBase64String", () => { it("[[Call]] returns the correct string", () => { - Object.entries(base64s).forEach(([key, value]) => + for (const [source, { base64 }] of data) { assertStrictEquals( - filenameSafeBase64String(value), - key.replace("+", "-").replace("/", "_"), - ) - ); + filenameSafeBase64String(source), + base64.replace("+", "-").replace("/", "_"), + ); + } + }); +}); + +describe("isBase16", () => { + it("[[Call]] returns true for base64 strings", () => { + for (const { base16 } of data.values()) { + assert(isBase16(base16)); + assert(isBase16(base16.toLowerCase())); + } + }); + + it("[[Call]] returns false for others", () => { + [ + undefined, + null, + true, + Symbol(), + 27, + 98n, + {}, + [], + () => {}, + new Proxy({}, {}), + "abc_", + "a", + "abc", + "abcg", + ].forEach((value) => assert(!isBase16(value))); + }); +}); + +describe("isBase32", () => { + it("[[Call]] returns true for base32 strings", () => { + for (const { base32 } of data.values()) { + assert(isBase32(base32)); + assert(isBase32(base32.toLowerCase())); + } + }); + + it("[[Call]] returns false for others", () => { + [ + undefined, + null, + true, + Symbol(), + 27, + 98n, + {}, + [], + () => {}, + new Proxy({}, {}), + "ABC1", + "A=======", + "ABCDEFGHI", + ].forEach((value) => assert(!isBase32(value))); }); }); describe("isBase64", () => { it("[[Call]] returns true for base64 strings", () => { - Object.keys(base64s).forEach((key) => assert(isBase64(key))); + for (const { base64 } of data.values()) { + assert(isBase64(base64)); + } }); it("[[Call]] returns false for others", () => { @@ -164,11 +661,13 @@ describe("isBase64", () => { describe("isFilenameSafeBase64", () => { it("[[Call]] returns true for filename‐safe base64 strings", () => { - Object.keys(base64s).forEach((key) => + for (const { base64 } of data.values()) { assert( - isFilenameSafeBase64(key.replace("+", "-").replace("/", "_")), - ) - ); + isFilenameSafeBase64( + base64.replace("+", "-").replace("/", "_"), + ), + ); + } }); it("[[Call]] returns false for others", () => { @@ -189,3 +688,200 @@ describe("isFilenameSafeBase64", () => { ].forEach((value) => assert(!isFilenameSafeBase64(value))); }); }); + +describe("isWRMGBase32", () => { + it("[[Call]] returns true for W·R·M·G base32 strings", () => { + for (const { wrmg } of data.values()) { + assert(isWRMGBase32(wrmg)); + assert(isWRMGBase32(wrmg.toLowerCase())); + assert(isWRMGBase32(`--${wrmg}--`)); + assert(isWRMGBase32(wrmg.replaceAll(/1/gu, "I"))); + assert(isWRMGBase32(wrmg.replaceAll(/1/gu, "L"))); + assert(isWRMGBase32(wrmg.replaceAll(/0/gu, "O"))); + assert(isWRMGBase32(wrmg.replaceAll(/1/gu, "i"))); + assert(isWRMGBase32(wrmg.replaceAll(/1/gu, "l"))); + assert(isWRMGBase32(wrmg.replaceAll(/0/gu, "o"))); + assert(isWRMGBase32(wrmg.replaceAll(/./gu, ($) => { + const rand = Math.random(); + return rand < 0.25 + ? $ + : rand < 0.5 + ? `-${$}` + : rand < 0.75 + ? `${$}-` + : `-${$}-`; + }))); + } + }); + + it("[[Call]] returns false for others", () => { + [ + undefined, + null, + true, + Symbol(), + 27, + 98n, + {}, + [], + () => {}, + new Proxy({}, {}), + "ABCU", + "A", + "ABCDEFGH1", + ].forEach((value) => assert(!isWRMGBase32(value))); + }); +}); + +describe("wrmgBase32Binary", () => { + it("[[Call]] returns the correct data", () => { + assertEquals( + new Uint8Array(wrmgBase32Binary("")), + new Uint8Array([]), + "", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("01H00R80EC06A01P00T0")), + Uint8Array.from( + "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4", + ($) => $.charCodeAt(0), + ), + "01H00R80EC06A01P00T0", + ); + assertEquals( + new Uint16Array(wrmgBase32Binary("8ZT0")), + new Uint16Array([62535]), + "8ZT0", + ); + assertEquals( + new Uint8ClampedArray(wrmgBase32Binary("9D4M4J8")), + new Uint8ClampedArray([75, 73, 66, 73]), + "9D4M4J8", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("C9GQ6S9P6G")), + new Uint8Array([98, 97, 115, 101, 54, 52]), + "C9GQ6S9P6G", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("2KXSR0YSFR")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), + "2KXSR0YSFR", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("2KXSR0YS")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), + "2KXSR0YS", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("2KXSR0R")), + new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), + "2KXSR0R", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("50")), + new Uint8Array([0x28]), + "50", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TR")), + new Uint8Array([0xD6]), + "TR", + ); + assertEquals( + new Uint16Array(wrmgBase32Binary("TVW0")), + new Uint16Array([0xF8D6]), + "TVW0", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVW00")), + new Uint8Array([0xD6, 0xF8, 0x00]), + "TVW00", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVW10")), + new Uint8Array([0xD6, 0xF8, 0x10]), + "TVW10", + ); + assertEquals( + new Uint32Array(wrmgBase32Binary("TVW1230")), + new Uint32Array([0x0C11F8D6]), + "TVW1230", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVW12340")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "TVW12340", + ); + assertEquals( + new Uint16Array(wrmgBase32Binary("TVW1234560")), + new Uint16Array([0xF8D6, 0x0C11, 0x3085]), + "TVW1234560", + ); + }); + + it("[[Call]] is case‐insensitive", () => { + assertEquals( + new Uint8Array(wrmgBase32Binary("tVw12340")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "tVw12340", + ); + }); + + it("[[Call]] casts I, L & O", () => { + assertEquals( + new Uint8Array(wrmgBase32Binary("TVWI234O")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "TVWI234O", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVWi234o")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "TVWi234o", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVWL234O")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "TVWL234O", + ); + assertEquals( + new Uint8Array(wrmgBase32Binary("TVWl234o")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "TVWl234o", + ); + }); + + it("[[Call]] ignores hyphens", () => { + assertEquals( + new Uint8Array(wrmgBase32Binary("--TVW---123-40-----")), + new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), + "--TVW---123-40-----", + ); + }); + + it("[[Call]] throws when provided with an invalid character", () => { + assertThrows(() => wrmgBase32Binary("ABCu")); + assertThrows(() => wrmgBase32Binary("ABCU")); + assertThrows(() => wrmgBase32Binary("ABC=")); + }); + + it("[[Call]] throws when provided with a length with a remainder of 1, 3 ∣ 6 when divided by 8", () => { + assertThrows(() => base32Binary("TVW123400")); + assertThrows(() => base32Binary("TVW123400=======")); + assertThrows(() => base32Binary("M78")); + assertThrows(() => base32Binary("M78M93")); + }); + + it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 4", () => { + assertThrows(() => wrmgBase32Binary("234BCDEAA")); + assertThrows(() => wrmgBase32Binary("2-34-B--CD-EA-A-")); + }); +}); + +describe("wrmgBase32String", () => { + it("[[Call]] returns the correct string", () => { + for (const [source, { wrmg }] of data) { + assertStrictEquals(wrmgBase32String(source), wrmg); + } + }); +});