function getUint64(inputArray, index, littleEndian) {
const dataView = new DataView(inputArray.buffer);
let hi = dataView.getUint32(index, littleEndian);
let lo = dataView.getUint32(index + 4, littleEndian);
if (littleEndian) {
const tmp = hi;
hi = lo;
lo = tmp;
}
if (hi > 0x1fffff) {
throw new Error(
'Cannot safely parse uints over 2^53 - 1 (0x1fffffffffffff) in to a 64 bit float.'
);
}
const numberValue = (hi * 0x100000000) + lo;
return numberValue;
}
// Tests gotten from this other excellent answer here: https://stackoverflow.com/a/53107482/628418
// [byteArray, littleEndian, expectedValue, expectError]
const testValues = [
// big-endian
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]), false, 255],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]), false, 65535],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]), false, 4294967295],
[new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]), false, 4294967296],
[new Uint8Array([0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), false, 9007199254740991], // maximum precision
[new Uint8Array([0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), false, 9007199254740992, true], // precision lost
[new Uint8Array([0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]), false, 9007199254740992, true], // precision lost
// little-endian
[new Uint8Array([0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), true, 255],
[new Uint8Array([0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), true, 65535],
[new Uint8Array([0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]), true, 4294967295],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]), true, 4294967296],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00]), true, 1099511627776],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]), true, 281474976710656],
[new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00]), true, 9007199254740991], // maximum precision
];
testValues.forEach(testGetUint64);
function testGetUint64([bytes, littleEndian, expectedValue, expectError]) {
if (expectError) {
try {
const val = getUint64(bytes, 0, littleEndian);
console.error('did not get the expected error');
} catch(error) {
console.log('got expected error: ' + error.message);
}
} else {
const val = getUint64(bytes, 0, littleEndian);
console.log(val === expectedValue? 'pass' : 'FAIL. expected '+expectedValue+', received '+val);
}
}