Search code examples
javascriptdataviewbigint

js DataView read from BigInt offset


I'm writing code to read a gimp XCF file in the browser, and from XCF version 11 and up a 'POINTER' data type is 64 bit instead of 32 bit for the sake of >4GB XCF files.

My issue is that I don't think DataView is capable of handling BigInt offsets with its get* functions. Reading BigInt from dataview yes, reading at BigInt offsets no.

Has anyone else encountered this, and if so how did you deal with it?

A snippet of my code:

word(signed: boolean = true): number {
  let result = signed ?
  this.view.getInt32(this.offset, false) :
  this.view.getUint32(this.offset, false);

  this.offset += 4;
  return result;
}

word64(signed: boolean = true): BigInt {
  let result = signed ?
  this.view.getBigInt64(this.offset, false) :
  this.view.getBigUint64(this.offset, false);

  this.offset += 8;
  return result;
}

pointer(xcfVersion: number): number | BigInt {
  if (xcfVersion < 11) {
    return this.word(false);
  } else {
    return this.word64(false);
  }
}

//....

let nv = 11; //XCF version 11

let ptr: BigInt|number = 0;
let layerPointers = new Array<BigInt|number>();

while ( (ptr = this.pointer(nv)) != 0) {
  console.log("layer pointer", ptr);
  layerPointers.push(ptr);
  if (ptr > this.view.byteLength) {
    console.log("gtr than allowed");
  }
  
  //Now I want to read 'this.view' at 'ptr' offset
  this.view.getUint32 (ptr);
  
  //yields: Uncaught TypeError: can't convert BigInt to number
}

Solution

  • The solution is to convert the 64-bit pointer to a Number:

    pointer(xcfVersion: number): number {
      if (xcfVersion < 11) {
        return this.word(false);
      } else {
        return Number(this.word64(false));
      }
    }
    

    Certainly, that won't cover the full 64-bit range, it's only safe up to 2**53. But that's fine, because ArrayBuffers are spec'ed to have 2**53 as their maximum size, so any ArrayBuffer that can be created, can be fully indexed this way.

    (Before you consider this a limitation, take a moment to think about how large that number is, and how long it'll be until XCF files might reach that size.)