I want to encode and decode Bytes from an Uint8Array (or an ArrayBuffer) to/from a string in Base36. JavaScript has the toString and parseInt functions which both support base36 but I am not sure if first converting 8 Bytes to a 64 bit floating point is the right idea.
In JS one can encode a BigInt (a number of arbitrary length) in Base36. However the other direction does not work.
How can I do this?
I found the solution with the help of these two posts: Why JavaScript base-36 conversion appears to be ambiguous and How to go between JS BigInts and TypedArrays
function bigIntToBase36(num){
return num.toString(36);
}
function base36ToBigInt(str){
return [...str].reduce((acc,curr) => BigInt(parseInt(curr, 36)) + BigInt(36) * acc, 0n);
}
function bigIntToBuffer(bn) {
let hex = BigInt(bn).toString(16);
if (hex.length % 2) { hex = '0' + hex; }
const len = hex.length / 2;
const u8 = new Uint8Array(len);
let i = 0;
let j = 0;
while (i < len) {
u8[i] = parseInt(hex.slice(j, j+2), 16);
i += 1;
j += 2;
}
return u8;
}
function bufferToBigInt(buf) {
const hex = [];
const u8 = Uint8Array.from(buf);
u8.forEach(function (i) {
var h = i.toString(16);
if (h.length % 2) { h = '0' + h; }
hex.push(h);
});
return BigInt('0x' + hex.join(''));
}
const t1 = new Uint8Array([123, 51, 234, 234, 24, 124, 2, 125, 34, 255]);
console.log(t1);
const t2 = bigIntToBase36(bufferToBigInt(t1));
console.log(t2);
console.log(t2.length)
const t3 = bigIntToBuffer(base36ToBigInt(t2));
console.log(t3);