dataReader.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { StringTools } from './stringTools';
  2. /**
  3. * Interface for a data buffer
  4. */
  5. export interface IDataBuffer {
  6. /**
  7. * Reads bytes from the data buffer.
  8. * @param byteOffset The byte offset to read
  9. * @param byteLength The byte length to read
  10. * @returns A promise that resolves when the bytes are read
  11. */
  12. readAsync(byteOffset: number, byteLength: number): Promise<ArrayBufferView>;
  13. /**
  14. * The byte length of the buffer.
  15. */
  16. readonly byteLength: number;
  17. }
  18. /**
  19. * Utility class for reading from a data buffer
  20. */
  21. export class DataReader {
  22. /**
  23. * The data buffer associated with this data reader.
  24. */
  25. public readonly buffer: IDataBuffer;
  26. /**
  27. * The current byte offset from the beginning of the data buffer.
  28. */
  29. public byteOffset = 0;
  30. private _dataView: DataView;
  31. private _dataByteOffset: number;
  32. /**
  33. * Constructor
  34. * @param buffer The buffer to read
  35. */
  36. constructor(buffer: IDataBuffer) {
  37. this.buffer = buffer;
  38. }
  39. /**
  40. * Loads the given byte length.
  41. * @param byteLength The byte length to load
  42. * @returns A promise that resolves when the load is complete
  43. */
  44. public loadAsync(byteLength: number): Promise<void> {
  45. delete this._dataView;
  46. delete this._dataByteOffset;
  47. return this.buffer.readAsync(this.byteOffset, byteLength).then((data) => {
  48. this._dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
  49. this._dataByteOffset = 0;
  50. });
  51. }
  52. /**
  53. * Read a unsigned 32-bit integer from the currently loaded data range.
  54. * @returns The 32-bit integer read
  55. */
  56. public readUint32(): number {
  57. const value = this._dataView.getUint32(this._dataByteOffset, true);
  58. this._dataByteOffset += 4;
  59. this.byteOffset += 4;
  60. return value;
  61. }
  62. /**
  63. * Read a byte array from the currently loaded data range.
  64. * @param byteLength The byte length to read
  65. * @returns The byte array read
  66. */
  67. public readUint8Array(byteLength: number): Uint8Array {
  68. const value = new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + this._dataByteOffset, byteLength);
  69. this._dataByteOffset += byteLength;
  70. this.byteOffset += byteLength;
  71. return value;
  72. }
  73. /**
  74. * Read a string from the currently loaded data range.
  75. * @param byteLength The byte length to read
  76. * @returns The string read
  77. */
  78. public readString(byteLength: number): string {
  79. return StringTools.Decode(this.readUint8Array(byteLength));
  80. }
  81. /**
  82. * Skips the given byte length the currently loaded data range.
  83. * @param byteLength The byte length to skip
  84. */
  85. public skipBytes(byteLength: number): void {
  86. this._dataByteOffset += byteLength;
  87. this.byteOffset += byteLength;
  88. }
  89. }