simple-buffer.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { defaults } from 'mol-util';
  8. export interface SimpleBuffer extends Uint8Array {
  9. readInt8: (offset: number) => number
  10. readUInt8: (offset: number) => number
  11. writeInt8: (value: number, offset: number) => void
  12. writeUInt8: (value: number, offset: number) => void
  13. readInt16LE: (offset: number) => number
  14. readInt32LE: (offset: number) => number
  15. readUInt16LE: (offset: number) => number
  16. readUInt32LE: (offset: number) => number
  17. readFloatLE: (offset: number) => number
  18. readDoubleLE: (offset: number) => number
  19. writeInt16LE: (value: number, offset: number) => void
  20. writeInt32LE: (value: number, offset: number) => void
  21. writeUInt16LE: (value: number, offset: number) => void
  22. writeUInt32LE: (value: number, offset: number) => void
  23. writeFloatLE: (value: number, offset: number) => void
  24. writeDoubleLE: (value: number, offset: number) => void
  25. readInt16BE: (offset: number) => number
  26. readInt32BE: (offset: number) => number
  27. readUInt16BE: (offset: number) => number
  28. readUInt32BE: (offset: number) => number
  29. readFloatBE: (offset: number) => number
  30. readDoubleBE: (offset: number) => number
  31. writeInt16BE: (value: number, offset: number) => void
  32. writeInt32BE: (value: number, offset: number) => void
  33. writeUInt16BE: (value: number, offset: number) => void
  34. writeUInt32BE: (value: number, offset: number) => void
  35. writeFloatBE: (value: number, offset: number) => void
  36. writeDoubleBE: (value: number, offset: number) => void
  37. copy: (targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number) => number
  38. }
  39. export namespace SimpleBuffer {
  40. export function fromUint8Array(array: Uint8Array): SimpleBuffer {
  41. const dv = new DataView(array.buffer)
  42. return Object.assign(array.subarray(0), {
  43. readInt8: (offset: number) => dv.getInt8(offset),
  44. readUInt8: (offset: number) => dv.getUint8(offset),
  45. writeInt8: (value: number, offset: number) => dv.setInt8(offset, value),
  46. writeUInt8: (value: number, offset: number) => dv.setUint8(offset, value),
  47. readInt16LE: (offset: number) => dv.getInt16(offset, true),
  48. readInt32LE: (offset: number) => dv.getInt32(offset, true),
  49. readUInt16LE: (offset: number) => dv.getUint16(offset, true),
  50. readUInt32LE: (offset: number) => dv.getUint32(offset, true),
  51. readFloatLE: (offset: number) => dv.getFloat32(offset, true),
  52. readDoubleLE: (offset: number) => dv.getFloat64(offset, true),
  53. writeInt16LE: (value: number, offset: number) => dv.setInt16(offset, value, true),
  54. writeInt32LE: (value: number, offset: number) => dv.setInt32(offset, value, true),
  55. writeUInt16LE: (value: number, offset: number) => dv.setUint16(offset, value, true),
  56. writeUInt32LE: (value: number, offset: number) => dv.setUint32(offset, value, true),
  57. writeFloatLE: (value: number, offset: number) => dv.setFloat32(offset, value, true),
  58. writeDoubleLE: (value: number, offset: number) => dv.setFloat64(offset, value, true),
  59. readInt16BE: (offset: number) => dv.getInt16(offset, false),
  60. readInt32BE: (offset: number) => dv.getInt32(offset, false),
  61. readUInt16BE: (offset: number) => dv.getUint16(offset, false),
  62. readUInt32BE: (offset: number) => dv.getUint32(offset, false),
  63. readFloatBE: (offset: number) => dv.getFloat32(offset, false),
  64. readDoubleBE: (offset: number) => dv.getFloat64(offset, false),
  65. writeInt16BE: (value: number, offset: number) => dv.setInt16(offset, value, false),
  66. writeInt32BE: (value: number, offset: number) => dv.setInt32(offset, value, false),
  67. writeUInt16BE: (value: number, offset: number) => dv.setUint16(offset, value, false),
  68. writeUInt32BE: (value: number, offset: number) => dv.setUint32(offset, value, false),
  69. writeFloatBE: (value: number, offset: number) => dv.setFloat32(offset, value, false),
  70. writeDoubleBE: (value: number, offset: number) => dv.setFloat64(offset, value, false),
  71. copy: (targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number) => {
  72. targetStart = defaults(targetStart, 0)
  73. sourceStart = defaults(sourceStart, 0)
  74. sourceEnd = defaults(sourceEnd, array.length)
  75. targetBuffer.set(array.subarray(sourceStart, sourceEnd), targetStart)
  76. return sourceEnd - sourceStart
  77. }
  78. })
  79. }
  80. export function fromArrayBuffer(arrayBuffer: ArrayBuffer): SimpleBuffer {
  81. return fromUint8Array(new Uint8Array(arrayBuffer))
  82. }
  83. export function fromBuffer(buffer: Buffer): SimpleBuffer {
  84. return buffer
  85. }
  86. export const IsNativeEndianLittle = new Uint16Array(new Uint8Array([0x12, 0x34]).buffer)[0] === 0x3412;
  87. /** source and target can't be the same */
  88. export function flipByteOrder(source: SimpleBuffer, target: Uint8Array, byteCount: number, elementByteSize: number, offset: number) {
  89. for (let i = 0, n = byteCount; i < n; i += elementByteSize) {
  90. for (let j = 0; j < elementByteSize; j++) {
  91. target[offset + i + elementByteSize - j - 1] = source[offset + i + j];
  92. }
  93. }
  94. }
  95. export function flipByteOrderInPlace2(buffer: ArrayBuffer, byteOffset = 0, length?: number) {
  96. const intView = new Int16Array(buffer, byteOffset, length)
  97. for (let i = 0, n = intView.length; i < n; ++i) {
  98. const val = intView[i]
  99. intView[i] = ((val & 0xff) << 8) | ((val >> 8) & 0xff)
  100. }
  101. }
  102. export function ensureLittleEndian(source: SimpleBuffer, target: SimpleBuffer, byteCount: number, elementByteSize: number, offset: number) {
  103. if (IsNativeEndianLittle) return;
  104. if (!byteCount || elementByteSize <= 1) return;
  105. flipByteOrder(source, target, byteCount, elementByteSize, offset);
  106. }
  107. }