Search code examples
javascriptphpnode.jsbinarybuffer

How do I unpack a data from a binary string in Node.js?


In PHP you can do this as follows:

$raw_data = base64_decode("1Xr5WEtvrApEByOh4GtDb1nDtls");
$unpacked = unpack('Vx/Vy', $raw_data);

/* output:
  array(2) {
    ["x"]=>
    int(1492744917)
    ["y"]=>
    int(179072843)
  }
*/ 

How do I achieve the same result in Node.js?

So far, I have tried this:

const base64URLDecode = (data) => {
  let buffer
  data = data.replace(/-/g, '+').replace(/_/g, '/')

  while (data.length % 4) {
    data += '='
  }

  if (data instanceof Buffer) {
    buffer = data
  } else {
    buffer = Buffer.from(data.toString(), 'binary')
  }

  return buffer.toString('base64')
}

const byteToUINT8 = (bytes) => {
  const byteLength = bytes.length
  const uint8Arr = new Uint8Array(byteLength)

  return uint8Arr.map((char, key) => bytes.charCodeAt(key))
}

const unpack = (binString) => {
  const byteChars = base64URLDecode(binString)
  const uint8Arr = byteToUINT8(byteChars)
  const uint32Arr = new Uint32Array(uint8Arr.buffer)

  return uint32Arr
}

unpack('1Xr5WEtvrApEByOh4GtDb1nDtls') // output: [1180980814, 2036880973, ...]

However, this is giving me a totally mismatched result in comparison with PHP's unpack. What am I doing wrong?


Solution

  • Checkout this snippet:

     const buf = Buffer.from("1Xr5WEtvrApEByOh4GtDb1nDtls", 'base64')
     const uint32array =  new Uint32Array(buf.buffer, buf.byteOffset, buf.length / Uint32Array.BYTES_PER_ELEMENT)
     // Variable uint32array presents:
     // Uint32Array(5) [
     // 1492744917,
     // ... ]
    

    The documentation about Nodejs TypedArray is here: Nodejs Buffer