UNPKG

@qix/bigint-serialiser

Version:

a transcoder for serialising JavaScript BigInt values to a Uint8Array or any other array-like object

77 lines (63 loc) 1.51 kB
const SIGNIFICANT_BITS = 7n, CONTINUE = 1n << SIGNIFICANT_BITS, REST_MASK = CONTINUE - 1n; function encode(value) { let out = { length: Infinity }; out.length = encodeInto(value, out); return Uint8Array.from(out); } function encodeInto(value, byteArray, offset = 0) { value = BigInt(value); if (value < 0) { value = -value; --value; value <<= 1n; value |= 1n; } else { value <<= 1n; } while (value >= CONTINUE && offset < byteArray.length) { byteArray[offset] = Number((value & REST_MASK) | CONTINUE); value >>= SIGNIFICANT_BITS; --value; ++offset; } if (offset >= byteArray.length) { throw new Error('insufficient space'); } byteArray[offset] = Number(value); ++offset; return offset; } function decode(byteArray, offset = 0) { return decodeWithOffset(byteArray, offset).value; } function decodeWithOffset(byteArray, startingOffset = 0) { let finalOffset = startingOffset; while (finalOffset < byteArray.length - 1 && (byteArray[finalOffset] & 0x80) === 0x80) { ++finalOffset; } let value = -1n; for (let offset = finalOffset; offset >= startingOffset; --offset) { ++value; value <<= SIGNIFICANT_BITS; value |= BigInt(byteArray[offset]) & REST_MASK; } if ((value & 1n) === 1n) { value >>= 1n; ++value; value = -value; } else { value >>= 1n; } return { value, followingOffset: finalOffset + 1, }; } export { encode, encodeInto, decode, decodeWithOffset, };