Search code examples
javascriptbinarybufferarraybuffertyped-arrays

Nodejs Javascript TypedArray to Buffer to String and Back Again


I'm trying to implement a serialization and deserialization of a repeating set of floats, using TypedArray to string (for saving across wire/disk), But it's not making it round trip


Solution

  • I got it working by using the ArrayBuffer to Buffer methods provided on the linked issue, the issue is I think I was treating them as arbitrary Typed Arrays rather than the native Uint8Array that I guess Buffers use. Here's the working version.

    var recordsPerWrite = 1;
    var ab = new ArrayBuffer(8 + 8 + 8 * recordsPerWrite);
    var f64ry = new Float64Array(ab);
    
    var records_added = 1;
    
    
    var i1 = records_added * 0;
    var i2 = records_added * 1;
    var i3 = records_added * 2;
    ////////////////////////////
    var timestamp = 1.1;
    var price = 2.2;
    var amount = 3.3;
    
    f64ry[i1] = timestamp;
    f64ry[i2] = price;
    f64ry[i3] = amount;
    
    console.log(f64ry[i1], f64ry[i2],f64ry[i3]);
    
    
        var buffer = toBuffer(ab);
        var st = buffer.toString('base64');
        console.log("ST '" + st + "'");
    
        var buffer2 = new Buffer(st, 'base64');
    
        var ab2 = toArrayBuffer(buffer2);
        var f64ry2 = new Float64Array(ab2);
    
    
    function toArrayBuffer(buffer) {
        var ab = new ArrayBuffer(buffer.length);
        var view = new Uint8Array(ab);
        for (var i = 0; i < buffer.length; ++i) {
            view[i] = buffer[i];
        }
        return ab;
    }
    function toBuffer(ab) {
        var buffer = new Buffer(ab.byteLength);
        var view = new Uint8Array(ab);
        for (var i = 0; i < buffer.length; ++i) {
            buffer[i] = view[i];
        }
        return buffer;
    }
    
    timestamp2 = f64ry2[i1];
    price2 = f64ry2[i2];
    amount2 = f64ry2[i3];
    
    console.log("IN " + timestamp, price, amount);
    console.log("OUT " + timestamp2, price2, amount2);
    

    OUTPUT

    SOURCE: 1.1 2.2 3.3
    CLONE: undefined undefined undefined  //expected 1.1 2.2 3.3
    

    I am using the approach linked here: Convert a binary NodeJS Buffer to JavaScript ArrayBuffer

    var ab = new ArrayBuffer(8 + 8 + 8);
    var f64ry = new Float64Array(ab);
    
    var records_added = 1;
    
    var i1 = records_added * 0;
    var i2 = records_added * 1;
    var i3 = records_added * 2;
    ////////////////////////////
    var timestamp = 1.1;
    var price = 2.2;
    var amount = 3.3;
    
    f64ry[i1] = timestamp;
    f64ry[i2] = price;
    f64ry[i3] = amount;
    
    console.log(f64ry[i1], f64ry[i2],f64ry[i3]); //shows correctly
    
        var buffer = new Buffer(ab.byteLength);
        for (var i = 0; i < f64ry.length; ++i) {
           // console.log(i + " " +f64ry[i]);
            buffer[i] = f64ry[i];
        }
        console.log("buffer '" + buffer + "'");
        var st = buffer.toString('hex');
        console.log("ST '" + st + "'");
        //var ab = buffer.toArrayBuffer(); //doesn't work in Node v.10
    
        var buffer2 = new Buffer(st, 'hex');
    
        console.log("buffer2 '" + buffer2 + "'");
        var ab2 = new ArrayBuffer(buffer2.byteLength);
        var f64ry2 = new Float64Array(ab2);
    
       for (var i = 0; i < buffer2.length; ++i) {
            console.log(i + " " +buffer2[i]);
            f64ry2[i] = buffer2[i];
        }
    
    
    }
    
    timestamp2 = f64ry2[i1];
    price2 = f64ry2[i2];
    amount2 = f64ry2[i3];
    
    console.log(timestamp, price, amount);
    console.log(timestamp2, price2, amount2);
    

    Similarly this alternate approach didn't work either:

    OUTPUT

    >1.1 2.2 3.3
    >buffer ''
    >ST '010203'
    >buffer2 ''
    >1.1 2.2 3.3
    >undefined undefined undefined
    

    CODE

    var f64ry = new Float64Array(3);
    var records_added = 1;
    
    
    var i1 = records_added * 0;
    var i2 = records_added * 1;
    var i3 = records_added * 2;
    ////////////////////////////
    var timestamp = 1.1;
    var price = 2.2;
    var amount = 3.3;
    
    var ary = [timestamp,price,amount];
    
    f64ry.set(ary,0);
    console.log(f64ry[i1], f64ry[i2],f64ry[i3]);
    
    
        var buffer = new Buffer(f64ry);
    
        console.log("buffer '" + buffer + "'");
        var st = buffer.toString('hex');
        console.log("ST '" + st + "'");
        //var ab = buffer.toArrayBuffer();
    
        var buffer2 = new Buffer(st, 'hex');
    
        console.log("buffer2 '" + buffer2 + "'");
        var ab2 = new ArrayBuffer(buffer2);
        var f64ry2 = new Float64Array(ab2);
    
    
    
    
    timestamp2 = f64ry2[i1];
    price2 = f64ry2[i2];
    amount2 = f64ry2[i3];
    
    console.log(timestamp, price, amount);
    console.log(timestamp2, price2, amount2);