/*
Base‑36 encoding/decoding in TypeScript
-------------------------------------------------
Base‑36 digits: 0–9, A–Z
Encoding:
- Convert string → bytes (UTF‑8)
- Convert bytes → BigInt (base‑256)
- Convert BigInt → base‑36 using toString(36)
Decoding:
- Convert base‑36 → BigInt
- Convert BigInt → bytes (base‑256)
- Convert bytes → original UTF‑8 string
TypeScript’s BigInt makes this clean and efficient.
*/
const BASE36_DIGITS: string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* Encode any UTF‑8 string into Base‑36.
*/
function encodeToBase36(text: string): string {
// Convert string → UTF‑8 bytes
const encoder: TextEncoder = new TextEncoder();
const bytes: Uint8Array = encoder.encode(text);
// Convert bytes → BigInt (base‑256)
let n: bigint = 0n;
for (const b of bytes) {
n = n * 256n + BigInt(b);
}
// Convert BigInt → Base‑36
return n.toString(36).toUpperCase();
}
/**
* Decode Base‑36 text back into the original UTF‑8 string.
*/
function decodeFromBase36(encoded: string): string {
encoded = encoded.toUpperCase();
// Convert Base‑36 → BigInt
let n: bigint = 0n;
for (const c of encoded) {
const digit: number = BASE36_DIGITS.indexOf(c);
n = n * 36n + BigInt(digit);
}
// Convert BigInt → bytes (base‑256)
const bytes: number[] = [];
while (n > 0n) {
const byte: number = Number(n % 256n);
bytes.push(byte);
n = n / 256n;
}
bytes.reverse();
// Convert bytes → UTF‑8 string
const decoder: TextDecoder = new TextDecoder();
return decoder.decode(new Uint8Array(bytes));
}
/**
* Usage
*/
function main(): void {
const text: string = "Hello Universe!";
const encoded: string = encodeToBase36(text);
const decoded: string = decodeFromBase36(encoded);
console.log("Original:", text);
console.log("Base-36 encoded:", encoded);
console.log("Decoded:", decoded);
}
main();
/*
run:
Original: Hello Universe!
Base-36 encoded: LP4N024HJ1YVBVD84Y8TYQP
Decoded: Hello Universe!
*/