pure.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. const BigInt32 = BigInt(32);
  2. export function getBigInt64(dataView: DataView, byteOffset: number, littleEndian: boolean | undefined): bigint {
  3. const littleEndianMask = Number(!!littleEndian);
  4. const bigEndianMask = Number(!littleEndian);
  5. return (
  6. BigInt(
  7. dataView.getInt32(byteOffset, littleEndian) * bigEndianMask +
  8. dataView.getInt32(byteOffset + 4, littleEndian) * littleEndianMask
  9. ) << BigInt32) |
  10. BigInt(
  11. dataView.getUint32(byteOffset, littleEndian) * littleEndianMask +
  12. dataView.getUint32(byteOffset + 4, littleEndian) * bigEndianMask
  13. );
  14. }
  15. export function getBigUint64(dataView: DataView, byteOffset: number, littleEndian: boolean | undefined): bigint {
  16. const a = dataView.getUint32(byteOffset, littleEndian);
  17. const b = dataView.getUint32(byteOffset + 4, littleEndian);
  18. const littleEndianMask = Number(!!littleEndian);
  19. const bigEndianMask = Number(!littleEndian);
  20. // This branch-less optimization is 77x faster than normal ternary operator.
  21. // and only 3% slower than native implementation
  22. // https://jsbench.me/p8kyhg1eqv/1
  23. return (BigInt(a * bigEndianMask + b * littleEndianMask) << BigInt32) |
  24. BigInt(a * littleEndianMask + b * bigEndianMask);
  25. };
  26. export function setBigInt64(dataView: DataView, byteOffset: number, value: bigint, littleEndian: boolean | undefined) {
  27. const hi = Number(value >> BigInt32);
  28. const lo = Number(value & BigInt(0xFFFFFFFF));
  29. if (littleEndian) {
  30. dataView.setInt32(byteOffset + 4, hi, littleEndian);
  31. dataView.setUint32(byteOffset, lo, littleEndian);
  32. } else {
  33. dataView.setInt32(byteOffset, hi, littleEndian);
  34. dataView.setUint32(byteOffset + 4, lo, littleEndian);
  35. }
  36. }
  37. export function setBigUint64(dataView: DataView, byteOffset: number, value: bigint, littleEndian: boolean | undefined) {
  38. const hi = Number(value >> BigInt32);
  39. const lo = Number(value & BigInt(0xFFFFFFFF));
  40. if (littleEndian) {
  41. dataView.setUint32(byteOffset + 4, hi, littleEndian);
  42. dataView.setUint32(byteOffset, lo, littleEndian);
  43. } else {
  44. dataView.setUint32(byteOffset, hi, littleEndian);
  45. dataView.setUint32(byteOffset + 4, lo, littleEndian);
  46. }
  47. };