Skip to content

Instantly share code, notes, and snippets.

@graup
Created November 12, 2018 20:18
Show Gist options
  • Save graup/815c9ac65c2bac8a56391f0ca23636fc to your computer and use it in GitHub Desktop.
Save graup/815c9ac65c2bac8a56391f0ca23636fc to your computer and use it in GitHub Desktop.
import JSBI from 'jsbi';
const useNativeBigIntsIfAvailable = true;
if (useNativeBigIntsIfAvailable) JSBI.useNativeBigIntsIfAvailable();
const BigInt = JSBI.BigInt
DataView.prototype._setBigUint64 = DataView.prototype.setBigUint64;
DataView.prototype.setBigUint64 = function(byteOffset, value, littleEndian) {
if (typeof value === 'bigint' && typeof this._setBigUint64 !== 'undefined') {
// the original native implementation for bigint
this._setBigUint64(byteOffset, value, littleEndian);
} else if (value.constructor === JSBI && typeof value.sign === 'bigint' && typeof this._setBigUint64 !== 'undefined') {
// JSBI wrapping a native bigint
this._setBigUint64(byteOffset, value.sign, littleEndian);
} else if (value.constructor === JSBI) {
// JSBI polyfill implementation
let lowWord = value[0], highWord = 0;
if (value.length >= 2) {
highWord = value[1];
}
this.setUint32(littleEndian ? 0 : 4, lowWord, littleEndian);
this.setUint32(littleEndian ? 4 : 0, highWord, littleEndian);
} else {
throw TypeError('Value needs to be BigInt ot JSBI');
}
}
DataView.prototype._getBigUint64 = DataView.prototype.getBigUint64;
DataView.prototype.getBigUint64 = function(byteOffset, littleEndian) {
if (typeof this._setBigUint64 !== 'undefined' && useNativeBigIntsIfAvailable) {
return BigInt(this._getBigUint64(byteOffset, littleEndian));
} else {
let lowWord = 0, highWord = 0;
lowWord = this.getUint32(littleEndian ? 0 : 4, littleEndian);
highWord = this.getUint32(littleEndian ? 4 : 0, littleEndian);
const result = new JSBI(2, false);
result.__setDigit(0, lowWord);
result.__setDigit(1, highWord);
return result;
}
}
const number = BigInt(String(2n ** 63n - 1n)); // '9223372036854775807'
console.log(number, String(number));
function toUint8Array(bigint, littleEndian = false) {
const arr = new ArrayBuffer(8);
const view = new DataView(arr);
view.setBigUint64(0, bigint, littleEndian);
return new Uint8Array(arr);
}
function fromUint8Array(uint8arr, littleEndian = false) {
const view = new DataView(uint8arr.buffer);
return view.getBigUint64(0, littleEndian);
}
const arr = toUint8Array(number, false);
console.log(arr);
console.log(fromUint8Array(arr, false), String(fromUint8Array(arr, false)));
const arr2 = toUint8Array(number, true);
console.log(arr2);
console.log(fromUint8Array(arr2, true), String(fromUint8Array(arr2, true)));
/*
Output for polyfilled implementation:
JSBI [ -1, 2147483647, sign: false ] '9223372036854775807'
Uint8Array [ 127, 255, 255, 255, 255, 255, 255, 255 ]
JSBI [ -1, 2147483647, sign: false ] '9223372036854775807'
Uint8Array [ 255, 255, 255, 255, 255, 255, 255, 127 ]
JSBI [ -1, 2147483647, sign: false ] '9223372036854775807'
Output for native implementation:
JSBI [ sign: 9223372036854775807n ] '9223372036854775807'
Uint8Array [ 127, 255, 255, 255, 255, 255, 255, 255 ]
JSBI [ sign: 9223372036854775807n ] '9223372036854775807'
Uint8Array [ 255, 255, 255, 255, 255, 255, 255, 127 ]
JSBI [ sign: 9223372036854775807n ] '9223372036854775807'
*/
@graup
Copy link
Author

graup commented Sep 10, 2020

Hi @glr0221, thanks for your comment! I see the original issue is still open. I tried to make this into a PR which didn't go anywhere, maybe you could try to contribute there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment