Search code examples
javascriptstringifyarraybufferuint64

Uint8Array(8) stringification


I'm getting unsigned 64-bit integer from the backend into ArrayBuffer, due to IEEE 754 I can't get&keep this sequence as a Number. Is there any way to "stringify" this huge number?

In a nutshell:

var buffer = new ArrayBuffer(8);
var raw = new Uint8Array(buffer);

raw[0] = 255;
raw[1] = 255;
raw[2] = 255;
raw[3] = 255;
raw[4] = 255;
raw[5] = 255;
raw[6] = 255;
raw[7] = 255;

var view = new DataView(buffer);
var result = view.getUint64(0); /// :-(

Thank you in advance.


Solution

  • Yes, you can stringify an Int64, but there is no "built in" way to do that since like you said JavaScript numbers are double precision floats.

    // ...
    function readInt64(view){
        var small = view.getUint32(0).toString(16); // present as base 16 string
        var large = view.getUint32(1).toString(16);
        // in a power-of-2  base it's just a string concat to add them
        var bigNumber = large + small; 
        return h2d(bigNumber);
    }
    

    Where h2d is taken from this answer here.

    function h2d(s) {
        // https://stackoverflow.com/a/12533838/1348195
        function add(x, y) {
            var c = 0, r = [];
            var x = x.split('').map(Number);
            var y = y.split('').map(Number);
            while(x.length || y.length) {
                var s = (x.pop() || 0) + (y.pop() || 0) + c;
                r.unshift(s < 10 ? s : s - 10); 
                c = s < 10 ? 0 : 1;
            }
            if(c) r.unshift(c);
            return r.join('');
        }
    
        var dec = '0';
        s.split('').forEach(function(chr) {
            var n = parseInt(chr, 16);
            for(var t = 8; t; t >>= 1) {
                dec = add(dec, dec);
                if(n & t) dec = add(dec, '1');
            }
        });
        return dec;
    }
    function readInt64(view, i){
        var small = view.getUint32(0 + 2 * i).toString(16); // present as base 16 string
        var large = view.getUint32(1 + 2 * i).toString(16);
        // in a power-of-2  base it's just a string concat to add them
        var bigNumber = large + small; 
        return h2d(bigNumber);
    }
    
    var buffer = new ArrayBuffer(8);
    var raw = new Uint8Array(buffer);
    
    raw[0] = 255;
    raw[1] = 255;
    raw[2] = 255;
    raw[3] = 255;
    raw[4] = 255;
    raw[5] = 255;
    raw[6] = 255;
    raw[7] = 255;
    
    var view = new DataView(buffer);
    var result = readInt64(view, 0);
    document.body.innerHTML = result;