UNPKG

@silvana-one/mina-utils

Version:
88 lines (81 loc) 2.99 kB
// URL friendly base64 encoding const TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; export function bigintToBase56(value: bigint): string { const digits = toBase(value, 56n); //console.log("digits:", digits); const str = digits.map((x) => TABLE[Number(x)]).join(""); //console.log("str:", str); return str; } export function bigintFromBase56(str: string): bigint { const base56Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x))); const x = fromBase(base56Digits, 56n); return x; } export function bigintToBase64(value: bigint): string { const digits = toBase(value, 64n); //console.log("digits:", digits); const str = digits.map((x) => TABLE[Number(x)]).join(""); //console.log("str:", str); return str; } export function bigintFromBase64(str: string): bigint { const base64Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x))); const x = fromBase(base64Digits, 64n); return x; } export function fromBase(digits: bigint[], base: bigint) { if (base <= 0n) throw Error("fromBase: base must be positive"); // compute powers base, base^2, base^4, ..., base^(2^k) // with largest k s.t. n = 2^k < digits.length let basePowers = []; for (let power = base, n = 1; n < digits.length; power **= 2n, n *= 2) { basePowers.push(power); } let k = basePowers.length; // pad digits array with zeros s.t. digits.length === 2^k digits = digits.concat(Array(2 ** k - digits.length).fill(0n)); // accumulate [x0, x1, x2, x3, ...] -> [x0 + base*x1, x2 + base*x3, ...] -> [x0 + base*x1 + base^2*(x2 + base*x3), ...] -> ... // until we end up with a single element for (let i = 0; i < k; i++) { let newDigits = Array(digits.length >> 1); let basePower = basePowers[i]; for (let j = 0; j < newDigits.length; j++) { newDigits[j] = digits[2 * j] + basePower * digits[2 * j + 1]; } digits = newDigits; } console.assert(digits.length === 1); let [digit] = digits; return digit; } export function toBase(x: bigint, base: bigint) { if (base <= 0n) throw Error("toBase: base must be positive"); // compute powers base, base^2, base^4, ..., base^(2^k) // with largest k s.t. base^(2^k) < x let basePowers = []; for (let power = base; power <= x; power **= 2n) { basePowers.push(power); } let digits = [x]; // single digit w.r.t base^(2^(k+1)) // successively split digits w.r.t. base^(2^j) into digits w.r.t. base^(2^(j-1)) // until we arrive at digits w.r.t. base let k = basePowers.length; for (let i = 0; i < k; i++) { let newDigits = Array(2 * digits.length); let basePower = basePowers[k - 1 - i]; for (let j = 0; j < digits.length; j++) { let x = digits[j]; let high = x / basePower; newDigits[2 * j + 1] = high; newDigits[2 * j] = x - high * basePower; } digits = newDigits; } // pop "leading" zero digits while (digits[digits.length - 1] === 0n) { digits.pop(); } return digits; }