├── .github └── workflows │ └── build.yml ├── .gitignore ├── KaitaiStream.ts ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json ├── rollup.config.mjs └── tsconfig.json /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: npm publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v0.[0-9]+.[0-9]+-SNAPSHOT.[0-9]+' 7 | 8 | jobs: 9 | publish-npm: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: '20' 16 | registry-url: https://registry.npmjs.org/ 17 | - run: npm ci 18 | - name: Check that KaitaiStream.js will be included 19 | run: | 20 | npm publish --tag next --dry-run --json | jq --exit-status '.files | map(.path) | any(. == "KaitaiStream.js")' 21 | - name: Publish to npm 22 | run: npm publish --tag next 23 | env: 24 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | 3 | # Generated by Typescript compiler 4 | /KaitaiStream.d.ts 5 | /KaitaiStream.js 6 | -------------------------------------------------------------------------------- /KaitaiStream.ts: -------------------------------------------------------------------------------- 1 | // -*- mode: js; js-indent-level: 2; -*- 2 | 3 | // Interfaces for optional dependencies 4 | interface IconvLite { 5 | decode(buffer: Buffer | Uint8Array, encoding: string): string 6 | } 7 | 8 | interface Zlib { 9 | inflateSync(buf: ArrayBuffer | NodeJS.ArrayBufferView): Buffer; 10 | } 11 | 12 | interface Pako { 13 | inflate(data: Uint8Array | number[]): Uint8Array; 14 | } 15 | 16 | // Workaround for https://github.com/microsoft/TypeScript/issues/36470 17 | declare global { 18 | interface CallableFunction { 19 | apply(this: (this: T, ...args: A[]) => R, thisArg: T, args: ArrayLike): R; 20 | } 21 | } 22 | 23 | // When loaded into a web worker, pako gets added to the global scope 24 | declare const pako: Pako; 25 | 26 | /** 27 | * KaitaiStream is an implementation of Kaitai Struct API for JavaScript. 28 | * Based on DataStream - https://github.com/kig/DataStream.js . 29 | */ 30 | class KaitaiStream { 31 | /** 32 | * @param arrayBuffer ArrayBuffer to read from. 33 | * @param byteOffset Offset from arrayBuffer beginning for the KaitaiStream. 34 | */ 35 | public constructor(arrayBuffer: ArrayBuffer | DataView | number, byteOffset?: number) { 36 | this._byteOffset = byteOffset || 0; 37 | if (arrayBuffer instanceof ArrayBuffer) { 38 | this.buffer = arrayBuffer; 39 | } else if (typeof arrayBuffer == "object") { 40 | this.dataView = arrayBuffer; 41 | if (byteOffset) { 42 | this._byteOffset += byteOffset; 43 | } 44 | } else { 45 | this.buffer = new ArrayBuffer(arrayBuffer || 1); 46 | } 47 | this.pos = 0; 48 | this.alignToByte(); 49 | } 50 | 51 | /** 52 | * Virtual byte length of the KaitaiStream backing buffer. 53 | * Updated to be max of original buffer size and last written size. 54 | * If dynamicSize is false is set to buffer size. 55 | */ 56 | private _byteLength = 0; 57 | private _byteOffset = 0; 58 | private _buffer!: ArrayBuffer; 59 | private _dataView!: DataView; 60 | 61 | public pos: number; 62 | public bits = 0; 63 | public bitsLeft = 0; 64 | 65 | /** 66 | * Dependency configuration data. Holds urls for (optional) dynamic loading 67 | * of code dependencies from a remote server. For use by (static) processing functions. 68 | * 69 | * Caller should the supported keys to the asset urls as needed. 70 | * NOTE: `depUrls` is a static property of KaitaiStream (the factory), like the various 71 | * processing functions. It is NOT part of the prototype of instances. 72 | */ 73 | public static depUrls: Record = { 74 | // processZlib uses this and expected a link to a copy of pako. 75 | // specifically the pako_inflate.min.js script at: 76 | // https://raw.githubusercontent.com/nodeca/pako/master/dist/pako_inflate.min.js 77 | zlib: undefined 78 | }; 79 | 80 | public static iconvlite?: IconvLite; 81 | public static zlib?: Pako | Zlib; 82 | 83 | /** 84 | * Gets the backing ArrayBuffer of the KaitaiStream object. 85 | * 86 | * @returns The backing ArrayBuffer. 87 | */ 88 | public get buffer(): ArrayBuffer { 89 | this._trimAlloc(); 90 | return this._buffer; 91 | } 92 | 93 | /** 94 | * Sets the backing ArrayBuffer of the KaitaiStream object and updates the 95 | * DataView to point to the new buffer. 96 | */ 97 | public set buffer(v: ArrayBuffer) { 98 | this._buffer = v; 99 | this._dataView = new DataView(this._buffer, this._byteOffset); 100 | this._byteLength = this._buffer.byteLength; 101 | } 102 | 103 | /** 104 | * Gets the byteOffset of the KaitaiStream object. 105 | * 106 | * @returns The byteOffset. 107 | */ 108 | public get byteOffset(): number { 109 | return this._byteOffset; 110 | } 111 | 112 | /** 113 | * Sets the byteOffset of the KaitaiStream object and updates the DataView to 114 | * point to the new byteOffset. 115 | */ 116 | public set byteOffset(v: number) { 117 | this._byteOffset = v; 118 | this._dataView = new DataView(this._buffer, this._byteOffset); 119 | this._byteLength = this._buffer.byteLength; 120 | } 121 | 122 | /** 123 | * Gets the backing DataView of the KaitaiStream object. 124 | * 125 | * @returns The backing DataView. 126 | */ 127 | public get dataView(): DataView { 128 | return this._dataView; 129 | } 130 | /** 131 | * Sets the backing DataView of the KaitaiStream object and updates the buffer 132 | * and byteOffset to point to the DataView values. 133 | */ 134 | public set dataView(v: DataView) { 135 | this._byteOffset = v.byteOffset; 136 | this._buffer = v.buffer; 137 | this._dataView = new DataView(this._buffer, this._byteOffset); 138 | this._byteLength = this._byteOffset + v.byteLength; 139 | } 140 | 141 | /** 142 | * Internal function to trim the KaitaiStream buffer when required. 143 | * Used for stripping out the extra bytes from the backing buffer when 144 | * the virtual byteLength is smaller than the buffer byteLength (happens after 145 | * growing the buffer with writes and not filling the extra space completely). 146 | */ 147 | private _trimAlloc(): void { 148 | if (this._byteLength === this._buffer.byteLength) { 149 | return; 150 | } 151 | const buf = new ArrayBuffer(this._byteLength); 152 | const dst = new Uint8Array(buf); 153 | const src = new Uint8Array(this._buffer, 0, dst.length); 154 | dst.set(src); 155 | this.buffer = buf; 156 | } 157 | 158 | // ======================================================================== 159 | // Stream positioning 160 | // ======================================================================== 161 | 162 | /** 163 | * Returns true if the KaitaiStream seek pointer is at the end of buffer and 164 | * there's no more data to read. 165 | * 166 | * @returns True if the seek pointer is at the end of the buffer. 167 | */ 168 | public isEof(): boolean { 169 | return this.pos >= this.size && this.bitsLeft === 0; 170 | } 171 | 172 | /** 173 | * Sets the KaitaiStream read/write position to given position. 174 | * Clamps between 0 and KaitaiStream length. 175 | * 176 | * @param pos Position to seek to. 177 | */ 178 | public seek(pos: number): void { 179 | const npos = Math.max(0, Math.min(this.size, pos)); 180 | this.pos = (isNaN(npos) || !isFinite(npos)) ? 0 : npos; 181 | } 182 | 183 | /** 184 | * Returns the byte length of the KaitaiStream object. 185 | * 186 | * @returns The byte length. 187 | */ 188 | public get size(): number { 189 | return this._byteLength - this._byteOffset; 190 | } 191 | 192 | // ======================================================================== 193 | // Integer numbers 194 | // ======================================================================== 195 | 196 | // ------------------------------------------------------------------------ 197 | // Signed 198 | // ------------------------------------------------------------------------ 199 | 200 | /** 201 | * Reads an 8-bit signed int from the stream. 202 | * 203 | * @returns The read number. 204 | */ 205 | public readS1(): number { 206 | this.ensureBytesLeft(1); 207 | const v = this._dataView.getInt8(this.pos); 208 | this.pos += 1; 209 | return v; 210 | } 211 | 212 | // ........................................................................ 213 | // Big-endian 214 | // ........................................................................ 215 | 216 | /** 217 | * Reads a 16-bit big-endian signed int from the stream. 218 | * 219 | * @returns The read number. 220 | */ 221 | public readS2be(): number { 222 | this.ensureBytesLeft(2); 223 | const v = this._dataView.getInt16(this.pos); 224 | this.pos += 2; 225 | return v; 226 | } 227 | 228 | /** 229 | * Reads a 32-bit big-endian signed int from the stream. 230 | * 231 | * @returns The read number. 232 | */ 233 | public readS4be(): number { 234 | this.ensureBytesLeft(4); 235 | const v = this._dataView.getInt32(this.pos); 236 | this.pos += 4; 237 | return v; 238 | } 239 | 240 | /** 241 | * Reads a 64-bit big-endian unsigned int from the stream. Note that 242 | * JavaScript does not support 64-bit integers natively, so it will 243 | * automatically upgrade internal representation to use IEEE 754 244 | * double precision float. 245 | * 246 | * @returns The read number. 247 | */ 248 | public readS8be(): number { 249 | this.ensureBytesLeft(8); 250 | const v1 = this.readU4be(); 251 | const v2 = this.readU4be(); 252 | 253 | if ((v1 & 0x80000000) !== 0) { 254 | // negative number 255 | return -(0x100000000 * (v1 ^ 0xffffffff) + (v2 ^ 0xffffffff)) - 1; 256 | } else { 257 | return 0x100000000 * v1 + v2; 258 | } 259 | } 260 | 261 | // ........................................................................ 262 | // Little-endian 263 | // ........................................................................ 264 | 265 | /** 266 | * Reads a 16-bit little-endian signed int from the stream. 267 | * 268 | * @returns The read number. 269 | */ 270 | public readS2le(): number { 271 | this.ensureBytesLeft(2); 272 | const v = this._dataView.getInt16(this.pos, true); 273 | this.pos += 2; 274 | return v; 275 | } 276 | 277 | /** 278 | * Reads a 32-bit little-endian signed int from the stream. 279 | * 280 | * @returns The read number. 281 | */ 282 | public readS4le(): number { 283 | this.ensureBytesLeft(4); 284 | const v = this._dataView.getInt32(this.pos, true); 285 | this.pos += 4; 286 | return v; 287 | } 288 | 289 | /** 290 | * Reads a 64-bit little-endian unsigned int from the stream. Note that 291 | * JavaScript does not support 64-bit integers natively, so it will 292 | * automatically upgrade internal representation to use IEEE 754 293 | * double precision float. 294 | * 295 | * @returns The read number. 296 | */ 297 | public readS8le(): number { 298 | this.ensureBytesLeft(8); 299 | const v1 = this.readU4le(); 300 | const v2 = this.readU4le(); 301 | 302 | if ((v2 & 0x80000000) !== 0) { 303 | // negative number 304 | return -(0x100000000 * (v2 ^ 0xffffffff) + (v1 ^ 0xffffffff)) - 1; 305 | } else { 306 | return 0x100000000 * v2 + v1; 307 | } 308 | } 309 | 310 | // ------------------------------------------------------------------------ 311 | // Unsigned 312 | // ------------------------------------------------------------------------ 313 | 314 | /** 315 | * Reads an 8-bit unsigned int from the stream. 316 | * 317 | * @returns The read number. 318 | */ 319 | public readU1(): number { 320 | this.ensureBytesLeft(1); 321 | const v = this._dataView.getUint8(this.pos); 322 | this.pos += 1; 323 | return v; 324 | } 325 | 326 | // ........................................................................ 327 | // Big-endian 328 | // ........................................................................ 329 | 330 | /** 331 | * Reads a 16-bit big-endian unsigned int from the stream. 332 | * 333 | * @returns The read number. 334 | */ 335 | public readU2be(): number { 336 | this.ensureBytesLeft(2); 337 | const v = this._dataView.getUint16(this.pos); 338 | this.pos += 2; 339 | return v; 340 | } 341 | 342 | /** 343 | * Reads a 32-bit big-endian unsigned int from the stream. 344 | * 345 | * @returns The read number. 346 | */ 347 | public readU4be(): number { 348 | this.ensureBytesLeft(4); 349 | const v = this._dataView.getUint32(this.pos); 350 | this.pos += 4; 351 | return v; 352 | } 353 | 354 | /** 355 | * Reads a 64-bit big-endian unsigned int from the stream. Note that 356 | * JavaScript does not support 64-bit integers natively, so it will 357 | * automatically upgrade internal representation to use IEEE 754 358 | * double precision float. 359 | * 360 | * @returns The read number. 361 | */ 362 | public readU8be(): number { 363 | this.ensureBytesLeft(8); 364 | const v1 = this.readU4be(); 365 | const v2 = this.readU4be(); 366 | return 0x100000000 * v1 + v2; 367 | } 368 | 369 | // ........................................................................ 370 | // Little-endian 371 | // ........................................................................ 372 | 373 | /** 374 | * Reads a 16-bit little-endian unsigned int from the stream. 375 | * 376 | * @returns The read number. 377 | */ 378 | public readU2le(): number { 379 | this.ensureBytesLeft(2); 380 | const v = this._dataView.getUint16(this.pos, true); 381 | this.pos += 2; 382 | return v; 383 | } 384 | 385 | /** 386 | * Reads a 32-bit little-endian unsigned int from the stream. 387 | * 388 | * @returns The read number. 389 | */ 390 | public readU4le(): number { 391 | this.ensureBytesLeft(4); 392 | const v = this._dataView.getUint32(this.pos, true); 393 | this.pos += 4; 394 | return v; 395 | } 396 | 397 | /** 398 | * Reads a 64-bit little-endian unsigned int from the stream. Note that 399 | * JavaScript does not support 64-bit integers natively, so it will 400 | * automatically upgrade internal representation to use IEEE 754 401 | * double precision float. 402 | * 403 | * @returns The read number. 404 | */ 405 | public readU8le(): number { 406 | this.ensureBytesLeft(8); 407 | const v1 = this.readU4le(); 408 | const v2 = this.readU4le(); 409 | return 0x100000000 * v2 + v1; 410 | } 411 | 412 | // ======================================================================== 413 | // Floating point numbers 414 | // ======================================================================== 415 | 416 | // ------------------------------------------------------------------------ 417 | // Big endian 418 | // ------------------------------------------------------------------------ 419 | 420 | /** 421 | * Reads a 32-bit big-endian float from the stream. 422 | * 423 | * @returns The read number. 424 | */ 425 | public readF4be(): number { 426 | this.ensureBytesLeft(4); 427 | const v = this._dataView.getFloat32(this.pos); 428 | this.pos += 4; 429 | return v; 430 | } 431 | 432 | /** 433 | * Reads a 64-bit big-endian float from the stream. 434 | * 435 | * @returns The read number. 436 | */ 437 | public readF8be(): number { 438 | this.ensureBytesLeft(8); 439 | const v = this._dataView.getFloat64(this.pos); 440 | this.pos += 8; 441 | return v; 442 | } 443 | 444 | // ------------------------------------------------------------------------ 445 | // Little endian 446 | // ------------------------------------------------------------------------ 447 | 448 | /** 449 | * Reads a 32-bit little-endian float from the stream. 450 | * 451 | * @returns The read number. 452 | */ 453 | public readF4le(): number { 454 | this.ensureBytesLeft(4); 455 | const v = this._dataView.getFloat32(this.pos, true); 456 | this.pos += 4; 457 | return v; 458 | } 459 | 460 | /** 461 | * Reads a 64-bit little-endian float from the stream. 462 | * 463 | * @returns The read number. 464 | */ 465 | public readF8le(): number { 466 | this.ensureBytesLeft(8); 467 | const v = this._dataView.getFloat64(this.pos, true); 468 | this.pos += 8; 469 | return v; 470 | } 471 | 472 | // ------------------------------------------------------------------------ 473 | // Unaligned bit values 474 | // ------------------------------------------------------------------------ 475 | 476 | /** 477 | * Aligns the stream position to the next byte boundary. 478 | */ 479 | public alignToByte(): void { 480 | this.bitsLeft = 0; 481 | this.bits = 0; 482 | } 483 | 484 | /** 485 | * @param n The number of bits to read. 486 | * @returns The read bits. 487 | * @throws {RangeError} 488 | */ 489 | public readBitsIntBe(n: number): number { 490 | // JS only supports bit operations on 32 bits 491 | if (n > 32) { 492 | throw new RangeError("readBitsIntBe: the maximum supported bit length is 32 (tried to read " + n + " bits)"); 493 | } 494 | let res = 0; 495 | 496 | const bitsNeeded = n - this.bitsLeft; 497 | this.bitsLeft = -bitsNeeded & 7; // `-bitsNeeded mod 8` 498 | 499 | if (bitsNeeded > 0) { 500 | // 1 bit => 1 byte 501 | // 8 bits => 1 byte 502 | // 9 bits => 2 bytes 503 | const bytesNeeded = ((bitsNeeded - 1) >> 3) + 1; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`) 504 | const buf = this.readBytes(bytesNeeded); 505 | for (let i = 0; i < bytesNeeded; i++) { 506 | res = res << 8 | buf[i]; 507 | } 508 | 509 | const newBits = res; 510 | res = res >>> this.bitsLeft | this.bits << bitsNeeded; // `x << 32` is defined as `x << 0` in JS, but only `0 << 32` 511 | // can occur here (`n = 32` and `bitsLeft = 0`, this implies 512 | // `bits = 0` unless changed externally) 513 | this.bits = newBits; // will be masked at the end of the function 514 | } else { 515 | res = this.bits >>> -bitsNeeded; // shift unneeded bits out 516 | } 517 | 518 | const mask = (1 << this.bitsLeft) - 1; // `bitsLeft` is in range 0..7, so `(1 << 32)` does not have to be considered 519 | this.bits &= mask; 520 | 521 | // always return an unsigned 32-bit integer 522 | return res >>> 0; 523 | } 524 | 525 | /** 526 | * Unused since Kaitai Struct Compiler v0.9+ - compatibility with older versions. 527 | * 528 | * @deprecated Use {@link readBitsIntBe} instead. 529 | * @param n The number of bits to read. 530 | * @returns The read bits. 531 | */ 532 | public readBitsInt(n: number): number { 533 | return this.readBitsIntBe(n); 534 | } 535 | 536 | /** 537 | * @param n The number of bits to read. 538 | * @returns The read bits. 539 | * @throws {RangeError} 540 | */ 541 | public readBitsIntLe(n: number): number { 542 | // JS only supports bit operations on 32 bits 543 | if (n > 32) { 544 | throw new RangeError("readBitsIntLe: the maximum supported bit length is 32 (tried to read " + n + " bits)"); 545 | } 546 | let res = 0; 547 | const bitsNeeded = n - this.bitsLeft; 548 | 549 | if (bitsNeeded > 0) { 550 | // 1 bit => 1 byte 551 | // 8 bits => 1 byte 552 | // 9 bits => 2 bytes 553 | const bytesNeeded = ((bitsNeeded - 1) >> 3) + 1; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`) 554 | const buf = this.readBytes(bytesNeeded); 555 | for (let i = 0; i < bytesNeeded; i++) { 556 | res |= buf[i] << (i * 8); 557 | } 558 | 559 | // NB: in JavaScript, bit shift operators always shift by modulo 32 of the right-hand operand (see 560 | // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-unsignedRightShift), 561 | // so `res >>> 32` is equivalent to `res >>> 0` (but we don't want that) 562 | const newBits = bitsNeeded < 32 ? res >>> bitsNeeded : 0; 563 | res = res << this.bitsLeft | this.bits; 564 | this.bits = newBits; 565 | } else { 566 | res = this.bits; 567 | this.bits >>>= n; 568 | } 569 | 570 | this.bitsLeft = -bitsNeeded & 7; // `-bitsNeeded mod 8` 571 | 572 | // always return an unsigned 32-bit integer 573 | if (n < 32) { 574 | const mask = (1 << n) - 1; 575 | res &= mask; // this produces a signed 32-bit int, but the sign bit is cleared 576 | } else { 577 | res >>>= 0; 578 | } 579 | return res; 580 | } 581 | 582 | /** 583 | * Native endianness. Either KaitaiStream.BIG_ENDIAN or KaitaiStream.LITTLE_ENDIAN 584 | * depending on the platform endianness. 585 | */ 586 | public static endianness: boolean = new Int8Array(new Int16Array([1]).buffer)[0] > 0; 587 | 588 | // ======================================================================== 589 | // Byte arrays 590 | // ======================================================================== 591 | 592 | /** 593 | * @param len The number of bytes to read. 594 | * @returns The read bytes. 595 | */ 596 | public readBytes(len: number): Uint8Array { 597 | return this.mapUint8Array(len); 598 | } 599 | 600 | /** 601 | * @returns The read bytes. 602 | */ 603 | public readBytesFull(): Uint8Array { 604 | return this.mapUint8Array(this.size - this.pos); 605 | } 606 | 607 | /** 608 | * Reads bytes until the terminator byte is found. 609 | * 610 | * @param terminator The terminator byte. 611 | * @param include True if the terminator should be included with the returned bytes. 612 | * @param consume True if the terminator should be consumed from the input stream. 613 | * @param eosError True to throw an error if the end of stream is reached. 614 | * @returns The read bytes. 615 | * @throws {string} 616 | */ 617 | public readBytesTerm(terminator: number, include: boolean, consume: boolean, eosError: boolean): Uint8Array { 618 | const blen = this.size - this.pos; 619 | const u8 = new Uint8Array(this._buffer, this._byteOffset + this.pos); 620 | let i; 621 | for (i = 0; i < blen && u8[i] !== terminator; i++); // find first zero byte 622 | if (i === blen) { 623 | // we've read all the buffer and haven't found the terminator 624 | if (eosError) { 625 | throw "End of stream reached, but no terminator " + terminator + " found"; 626 | } else { 627 | return this.mapUint8Array(i); 628 | } 629 | } else { 630 | let arr; 631 | if (include) { 632 | arr = this.mapUint8Array(i + 1); 633 | } else { 634 | arr = this.mapUint8Array(i); 635 | } 636 | if (consume) { 637 | this.pos += 1; 638 | } 639 | return arr; 640 | } 641 | } 642 | 643 | /** 644 | * Reads bytes until the terminator byte sequence is found. 645 | * 646 | * @param terminator The terminator byte sequence. 647 | * @param include True if the terminator should be included with the returned bytes. 648 | * @param consume True if the terminator should be consumed from the input stream. 649 | * @param eosError True to throw an error if the end of stream is reached. 650 | * @returns The read bytes. 651 | * @throws {string} 652 | */ 653 | public readBytesTermMulti(terminator: Uint8Array, include: boolean, consume: boolean, eosError: boolean): Uint8Array { 654 | const unitSize = terminator.length; 655 | const data = new Uint8Array(this._buffer, this._byteOffset + this.pos, this.size - this.pos); 656 | let res = KaitaiStream.bytesTerminateMulti(data, terminator, true); 657 | this.pos += res.length; 658 | const termFound = 659 | res.length !== 0 && 660 | res.length % unitSize === 0 && 661 | KaitaiStream.byteArrayCompare(new Uint8Array(res.buffer, res.length - unitSize), terminator) === 0; 662 | if (termFound) { 663 | if (!include) { 664 | res = new Uint8Array(res.buffer, res.byteOffset, res.length - unitSize); 665 | } 666 | if (!consume) { 667 | this.pos -= unitSize; 668 | } 669 | } else if (eosError) { 670 | throw new Error("End of stream reached, but no terminator " + terminator + " found"); 671 | } 672 | return res; 673 | } 674 | 675 | /** 676 | * Unused since Kaitai Struct Compiler v0.9+ - compatibility with older versions. 677 | * 678 | * @param expected The expected bytes. 679 | * @returns The read bytes. 680 | * @throws {KaitaiStream.UnexpectedDataError} 681 | */ 682 | public ensureFixedContents(expected: ArrayLike): Uint8Array { 683 | const actual = this.readBytes(expected.length); 684 | if (actual.length !== expected.length) { 685 | throw new KaitaiStream.UnexpectedDataError(expected, actual); 686 | } 687 | const actLen = actual.length; 688 | for (let i = 0; i < actLen; i++) { 689 | if (actual[i] !== expected[i]) { 690 | throw new KaitaiStream.UnexpectedDataError(expected, actual); 691 | } 692 | } 693 | return actual; 694 | } 695 | 696 | /** 697 | * @param data The data. 698 | * @param padByte The byte to strip. 699 | * @returns The stripped data. 700 | */ 701 | public static bytesStripRight(data: Uint8Array, padByte: number): Uint8Array { 702 | let newLen = data.length; 703 | while (data[newLen - 1] === padByte) { 704 | newLen--; 705 | } 706 | return data.slice(0, newLen); 707 | } 708 | 709 | /** 710 | * @param data The data. 711 | * @param term The terminator. 712 | * @param include True if the returned bytes should include the terminator. 713 | * @returns The terminated bytes. 714 | */ 715 | public static bytesTerminate(data: Uint8Array, term: number, include: boolean): Uint8Array { 716 | let newLen = 0; 717 | const maxLen = data.length; 718 | while (newLen < maxLen && data[newLen] !== term) { 719 | newLen++; 720 | } 721 | if (include && newLen < maxLen) 722 | newLen++; 723 | return data.slice(0, newLen); 724 | } 725 | 726 | /** 727 | * @param data The data. 728 | * @param term The terminator. 729 | * @param include True if the returned bytes should include the terminator. 730 | * @returns The terminated bytes. 731 | */ 732 | public static bytesTerminateMulti(data: Uint8Array, term: Uint8Array, include: boolean): Uint8Array { 733 | const unitSize = term.length; 734 | if (unitSize === 0) { 735 | return new Uint8Array(); 736 | } 737 | const len = data.length; 738 | let iTerm = 0; 739 | for (let iData = 0; iData < len;) { 740 | if (data[iData] !== term[iTerm]) { 741 | iData += unitSize - iTerm; 742 | iTerm = 0; 743 | continue; 744 | } 745 | iData++; 746 | iTerm++; 747 | if (iTerm === unitSize) { 748 | return data.slice(0, iData - (include ? 0 : unitSize)); 749 | } 750 | } 751 | return data.slice(); 752 | } 753 | 754 | /** 755 | * @param arr The bytes. 756 | * @param encoding The character encoding. 757 | * @returns The decoded string. 758 | */ 759 | public static bytesToStr(arr: Uint8Array, encoding: string): string { 760 | if (encoding == null || encoding.toLowerCase() === "ascii") { 761 | return KaitaiStream.createStringFromArray(arr); 762 | } else { 763 | if (typeof TextDecoder === 'function') { 764 | // we're in a browser that supports TextDecoder, or in Node.js 11 or later 765 | return (new TextDecoder(encoding)).decode(arr); 766 | } else { 767 | // probably we're in Node.js < 11 768 | 769 | // check if it's supported natively by Node.js Buffer 770 | // see https://nodejs.org/docs/latest-v10.x/api/buffer.html#buffer_buffers_and_character_encodings 771 | switch (encoding.toLowerCase()) { 772 | case 'utf8': 773 | case 'utf-8': 774 | case 'ucs2': 775 | case 'ucs-2': 776 | case 'utf16le': 777 | case 'utf-16le': 778 | return Buffer.from(arr).toString(encoding as BufferEncoding); 779 | default: 780 | // unsupported encoding, we'll have to resort to iconv-lite 781 | if (typeof KaitaiStream.iconvlite === 'undefined') 782 | KaitaiStream.iconvlite = require('iconv-lite') as IconvLite; 783 | 784 | return KaitaiStream.iconvlite.decode(arr, encoding); 785 | } 786 | } 787 | } 788 | } 789 | 790 | // ======================================================================== 791 | // Byte array processing 792 | // ======================================================================== 793 | 794 | /** 795 | * @param data The input bytes. 796 | * @param key The key byte. 797 | * @returns The Xor'd bytes. 798 | */ 799 | public static processXorOne(data: Uint8Array, key: number): Uint8Array { 800 | const r = new Uint8Array(data.length); 801 | const dl = data.length; 802 | for (let i = 0; i < dl; i++) 803 | r[i] = data[i] ^ key; 804 | return r; 805 | } 806 | 807 | /** 808 | * @param data The input bytes. 809 | * @param key The key bytes. 810 | * @returns The Xor'd bytes. 811 | */ 812 | public static processXorMany(data: Uint8Array, key: Uint8Array): Uint8Array { 813 | const dl = data.length; 814 | const r = new Uint8Array(dl); 815 | const kl = key.length; 816 | let ki = 0; 817 | for (let i = 0; i < dl; i++) { 818 | r[i] = data[i] ^ key[ki]; 819 | ki++; 820 | if (ki >= kl) 821 | ki = 0; 822 | } 823 | return r; 824 | } 825 | 826 | /** 827 | * @param data The input bytes. 828 | * @param amount The shift amount in bits. 829 | * @param groupSize The number of bytes in each group. 830 | * @returns The rotated bytes. 831 | * @throws {string} 832 | */ 833 | public static processRotateLeft(data: Uint8Array, amount: number, groupSize: number): Uint8Array { 834 | if (groupSize !== 1) 835 | throw ("unable to rotate group of " + groupSize + " bytes yet"); 836 | 837 | const mask = groupSize * 8 - 1; 838 | const antiAmount = -amount & mask; 839 | 840 | const r = new Uint8Array(data.length); 841 | for (let i = 0; i < data.length; i++) 842 | r[i] = (data[i] << amount) & 0xff | (data[i] >> antiAmount); 843 | 844 | return r; 845 | } 846 | 847 | /** 848 | * @param buf The input bytes. 849 | * @returns The uncompressed bytes. 850 | */ 851 | public static processZlib(buf: Uint8Array): Uint8Array { 852 | if (typeof require !== 'undefined') { 853 | // require is available - we're running under node 854 | if (typeof KaitaiStream.zlib === 'undefined') 855 | KaitaiStream.zlib = require('zlib') as Zlib; 856 | // use node's zlib module API 857 | const r = (KaitaiStream.zlib as Zlib).inflateSync( 858 | Buffer.from(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)) 859 | ); 860 | return new Uint8Array(r.buffer, r.byteOffset, r.length); 861 | } else { 862 | // no require() - assume we're running as a web worker in browser. 863 | // user should have configured KaitaiStream.depUrls.zlib, if not 864 | // we'll throw. 865 | if (typeof KaitaiStream.zlib === 'undefined' 866 | && typeof KaitaiStream.depUrls.zlib !== 'undefined') { 867 | importScripts(KaitaiStream.depUrls.zlib); 868 | KaitaiStream.zlib = pako; 869 | } 870 | // use pako API 871 | return (KaitaiStream.zlib as Pako).inflate(buf); 872 | } 873 | } 874 | 875 | // ======================================================================== 876 | // Misc runtime operations 877 | // ======================================================================== 878 | 879 | /** 880 | * @param a The dividend. 881 | * @param b The divisor. 882 | * @returns The result of `a` mod `b`. 883 | * @throws {string} 884 | */ 885 | public static mod(a: number, b: number): number { 886 | if (b <= 0) 887 | throw "mod divisor <= 0"; 888 | let r = a % b; 889 | if (r < 0) 890 | r += b; 891 | return r; 892 | } 893 | 894 | /** 895 | * Gets the smallest value in an array. 896 | * 897 | * @param arr The input array. 898 | * @returns The smallest value. 899 | */ 900 | public static arrayMin(arr: ArrayLike): number { 901 | let min = arr[0]; 902 | let x; 903 | for (let i = 1, n = arr.length; i < n; ++i) { 904 | x = arr[i]; 905 | if (x < min) min = x; 906 | } 907 | return min; 908 | } 909 | 910 | /** 911 | * Gets the largest value in an array. 912 | * 913 | * @param arr The input array. 914 | * @returns The largest value. 915 | */ 916 | public static arrayMax(arr: ArrayLike): number { 917 | let max = arr[0]; 918 | let x; 919 | for (let i = 1, n = arr.length; i < n; ++i) { 920 | x = arr[i]; 921 | if (x > max) max = x; 922 | } 923 | return max; 924 | } 925 | 926 | /** 927 | * Compares two arrays of bytes from left to right. 928 | * 929 | * @param a The first array. 930 | * @param b The second array. 931 | * @returns `0` if the arrays are the equal, a positive number if `a` is greater than `b`, or a negative number if `a` is less than `b`. 932 | */ 933 | public static byteArrayCompare(a: Uint8Array, b: Uint8Array): number { 934 | if (a === b) 935 | return 0; 936 | const al = a.length; 937 | const bl = b.length; 938 | const minLen = al < bl ? al : bl; 939 | for (let i = 0; i < minLen; i++) { 940 | const cmp = a[i] - b[i]; 941 | if (cmp !== 0) 942 | return cmp; 943 | } 944 | 945 | // Reached the end of at least one of the arrays 946 | if (al === bl) { 947 | return 0; 948 | } else { 949 | return al - bl; 950 | } 951 | } 952 | 953 | // ======================================================================== 954 | // Internal implementation details 955 | // ======================================================================== 956 | 957 | public static EOFError = class EOFError extends Error { 958 | public name = "EOFError"; 959 | public bytesReq: number; 960 | public bytesAvail: number; 961 | 962 | /** 963 | * @param bytesReq The number of bytes requested. 964 | * @param bytesAvail The number of bytes available. 965 | */ 966 | public constructor(bytesReq: number, bytesAvail: number) { 967 | super("requested " + bytesReq + " bytes, but only " + bytesAvail + " bytes available"); 968 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 969 | Object.setPrototypeOf(this, KaitaiStream.EOFError.prototype); 970 | this.bytesReq = bytesReq; 971 | this.bytesAvail = bytesAvail; 972 | } 973 | }; 974 | 975 | /** 976 | * Unused since Kaitai Struct Compiler v0.9+ - compatibility with older versions. 977 | */ 978 | public static UnexpectedDataError = class UnexpectedDataError extends Error { 979 | public name = "UnexpectedDataError"; 980 | public expected: any; 981 | public actual: any; 982 | 983 | /** 984 | * @param expected The expected value. 985 | * @param actual The actual value. 986 | */ 987 | public constructor(expected: any, actual: any) { 988 | super("expected [" + expected + "], but got [" + actual + "]"); 989 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 990 | Object.setPrototypeOf(this, KaitaiStream.UnexpectedDataError.prototype); 991 | this.expected = expected; 992 | this.actual = actual; 993 | } 994 | }; 995 | 996 | public static UndecidedEndiannessError = class UndecidedEndiannessError extends Error { 997 | public name = "UndecidedEndiannessError"; 998 | 999 | public constructor() { 1000 | super(); 1001 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1002 | Object.setPrototypeOf(this, KaitaiStream.UndecidedEndiannessError.prototype); 1003 | } 1004 | }; 1005 | 1006 | public static ValidationNotEqualError = class ValidationNotEqualError extends Error { 1007 | public name = "ValidationNotEqualError"; 1008 | public expected: any; 1009 | public actual: any; 1010 | 1011 | /** 1012 | * @param expected The expected value. 1013 | * @param actual The actual value. 1014 | */ 1015 | public constructor(expected: any, actual: any) { 1016 | super("not equal, expected [" + expected + "], but got [" + actual + "]"); 1017 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1018 | Object.setPrototypeOf(this, KaitaiStream.ValidationNotEqualError.prototype); 1019 | this.expected = expected; 1020 | this.actual = actual; 1021 | } 1022 | }; 1023 | 1024 | public static ValidationLessThanError = class ValidationLessThanError extends Error { 1025 | public name = "ValidationLessThanError"; 1026 | public min: any; 1027 | public actual: any; 1028 | 1029 | /** 1030 | * @param min The minimum allowed value. 1031 | * @param actual The actual value. 1032 | */ 1033 | public constructor(min: any, actual: any) { 1034 | super("not in range, min [" + min + "], but got [" + actual + "]"); 1035 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1036 | Object.setPrototypeOf(this, KaitaiStream.ValidationLessThanError.prototype); 1037 | this.min = min; 1038 | this.actual = actual; 1039 | } 1040 | }; 1041 | 1042 | public static ValidationGreaterThanError = class ValidationGreaterThanError extends Error { 1043 | public name = "ValidationGreaterThanError"; 1044 | public max: any; 1045 | public actual: any; 1046 | 1047 | /** 1048 | * @param max The maximum allowed value. 1049 | * @param actual The actual value. 1050 | */ 1051 | public constructor(max: any, actual: any) { 1052 | super("not in range, max [" + max + "], but got [" + actual + "]"); 1053 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1054 | Object.setPrototypeOf(this, KaitaiStream.ValidationGreaterThanError.prototype); 1055 | this.max = max; 1056 | this.actual = actual; 1057 | } 1058 | }; 1059 | 1060 | public static ValidationNotAnyOfError = class ValidationNotAnyOfError extends Error { 1061 | public name = "ValidationNotAnyOfError"; 1062 | public actual: any; 1063 | 1064 | /** 1065 | * @param actual The actual value. 1066 | */ 1067 | public constructor(actual: any) { 1068 | super("not any of the list, got [" + actual + "]"); 1069 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1070 | Object.setPrototypeOf(this, KaitaiStream.ValidationNotAnyOfError.prototype); 1071 | this.actual = actual; 1072 | } 1073 | }; 1074 | 1075 | public static ValidationNotInEnumError = class ValidationNotInEnumError extends Error { 1076 | public name = "ValidationNotInEnumError"; 1077 | public actual: any; 1078 | 1079 | /** 1080 | * @param actual The actual value. 1081 | */ 1082 | public constructor(actual: any) { 1083 | super("not in the enum, got [" + actual + "]"); 1084 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1085 | Object.setPrototypeOf(this, KaitaiStream.ValidationNotInEnumError.prototype); 1086 | this.actual = actual; 1087 | } 1088 | }; 1089 | 1090 | public static ValidationExprError = class ValidationExprError extends Error { 1091 | public name = "ValidationExprError"; 1092 | public actual: any; 1093 | 1094 | /** 1095 | * @param actual The actual value. 1096 | */ 1097 | public constructor(actual: any) { 1098 | super("not matching the expression, got [" + actual + "]"); 1099 | // Workaround https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types 1100 | Object.setPrototypeOf(this, KaitaiStream.ValidationExprError.prototype); 1101 | this.actual = actual; 1102 | } 1103 | }; 1104 | 1105 | /** 1106 | * Ensures that we have at least `length` bytes left in the stream. 1107 | * If not, throws an EOFError. 1108 | * 1109 | * @param length Number of bytes to require. 1110 | * @throws {KaitaiStream.EOFError} 1111 | */ 1112 | public ensureBytesLeft(length: number): void { 1113 | if (this.pos + length > this.size) { 1114 | throw new KaitaiStream.EOFError(length, this.size - this.pos); 1115 | } 1116 | } 1117 | 1118 | /** 1119 | * Maps a Uint8Array into the KaitaiStream buffer. 1120 | * Nice for quickly reading in data. 1121 | * 1122 | * @param length Number of elements to map. 1123 | * @returns A Uint8Array to the KaitaiStream backing buffer. 1124 | */ 1125 | public mapUint8Array(length: number): Uint8Array { 1126 | length |= 0; 1127 | 1128 | this.ensureBytesLeft(length); 1129 | 1130 | const arr = new Uint8Array(this._buffer, this.byteOffset + this.pos, length); 1131 | this.pos += length; 1132 | return arr; 1133 | } 1134 | 1135 | /** 1136 | * Creates an array from an array of character codes. 1137 | * Uses String.fromCharCode in chunks for memory efficiency and then concatenates 1138 | * the resulting string chunks. 1139 | * 1140 | * @param array Array of character codes. 1141 | * @returns String created from the character codes. 1142 | */ 1143 | public static createStringFromArray(array: Uint8Array): string { 1144 | const chunk_size = 0x8000; 1145 | const chunks = []; 1146 | for (let i = 0; i < array.length; i += chunk_size) { 1147 | const chunk = array.subarray(i, i + chunk_size); 1148 | chunks.push(String.fromCharCode.apply(null, chunk)); 1149 | } 1150 | return chunks.join(""); 1151 | } 1152 | } 1153 | 1154 | export default KaitaiStream; 1155 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kaitai Struct: runtime library for JavaScript 2 | 3 | [![npm@latest](https://img.shields.io/npm/v/kaitai-struct/latest)](https://www.npmjs.com/package/kaitai-struct/v/latest) 4 | [![npm@next](https://img.shields.io/npm/v/kaitai-struct/next)](https://www.npmjs.com/package/kaitai-struct/v/next) 5 | [![downloads](https://img.shields.io/npm/dw/kaitai-struct)](https://www.npmtrends.com/kaitai-struct) 6 | 7 | This library implements Kaitai Struct API for JavaScript. 8 | 9 | Kaitai Struct is a declarative language used for describe various binary 10 | data structures, laid out in files or in memory: i.e. binary file 11 | formats, network stream packet formats, etc. 12 | 13 | Further reading: 14 | 15 | * [About Kaitai Struct](http://kaitai.io/) 16 | * [About API implemented in this library](http://doc.kaitai.io/stream_api.html) 17 | * [JavaScript-specific notes](http://doc.kaitai.io/lang_javascript.html) - also includes Quick start guide 18 | 19 | ## Development 20 | 21 | After cloning this repository, you must run these commands to compile the 22 | TypeScript source file [`KaitaiStream.ts`](./KaitaiStream.ts) into the 23 | `KaitaiStream.js` file (ignored by Git) with JavaScript code: 24 | 25 | ```shell 26 | npm install 27 | npm run build 28 | ``` 29 | 30 | `npm run build` also needs to be run after each change to 31 | [`KaitaiStream.ts`](./KaitaiStream.ts). 32 | 33 | ## Licensing 34 | 35 | Copyright 2012-2016 Ilmari Heikkinen\ 36 | Copyright 2016-2024 Kaitai Project 37 | 38 | Licensed under the Apache License, Version 2.0 (the "License"); 39 | you may not use this file except in compliance with the License. 40 | You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 41 | 42 | Unless required by applicable law or agreed to in writing, software 43 | distributed under the License is distributed on an "AS IS" BASIS, 44 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 | See the License for the specific language governing permissions and 46 | limitations under the License. 47 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import KaitaiStream = require("./KaitaiStream"); 2 | declare const _default: { 3 | KaitaiStream: typeof KaitaiStream; 4 | }; 5 | export = _default; 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var KaitaiStream = require('./KaitaiStream.js'); 2 | 3 | module.exports = { 4 | KaitaiStream: KaitaiStream, 5 | }; 6 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kaitai-struct", 3 | "version": "0.11.0-SNAPSHOT.3", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "kaitai-struct", 9 | "version": "0.11.0-SNAPSHOT.3", 10 | "license": "Apache-2.0", 11 | "devDependencies": { 12 | "@rollup/plugin-typescript": "^12.1.2", 13 | "@types/node": "^16.11.11", 14 | "rollup": "^4.35.0", 15 | "tslib": "^2.3.1", 16 | "typescript": "^5.8.2" 17 | } 18 | }, 19 | "node_modules/@rollup/plugin-typescript": { 20 | "version": "12.1.2", 21 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.2.tgz", 22 | "integrity": "sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==", 23 | "dev": true, 24 | "license": "MIT", 25 | "dependencies": { 26 | "@rollup/pluginutils": "^5.1.0", 27 | "resolve": "^1.22.1" 28 | }, 29 | "engines": { 30 | "node": ">=14.0.0" 31 | }, 32 | "peerDependencies": { 33 | "rollup": "^2.14.0||^3.0.0||^4.0.0", 34 | "tslib": "*", 35 | "typescript": ">=3.7.0" 36 | }, 37 | "peerDependenciesMeta": { 38 | "rollup": { 39 | "optional": true 40 | }, 41 | "tslib": { 42 | "optional": true 43 | } 44 | } 45 | }, 46 | "node_modules/@rollup/pluginutils": { 47 | "version": "5.1.4", 48 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", 49 | "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", 50 | "dev": true, 51 | "license": "MIT", 52 | "dependencies": { 53 | "@types/estree": "^1.0.0", 54 | "estree-walker": "^2.0.2", 55 | "picomatch": "^4.0.2" 56 | }, 57 | "engines": { 58 | "node": ">=14.0.0" 59 | }, 60 | "peerDependencies": { 61 | "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" 62 | }, 63 | "peerDependenciesMeta": { 64 | "rollup": { 65 | "optional": true 66 | } 67 | } 68 | }, 69 | "node_modules/@rollup/rollup-android-arm-eabi": { 70 | "version": "4.37.0", 71 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", 72 | "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", 73 | "cpu": [ 74 | "arm" 75 | ], 76 | "dev": true, 77 | "license": "MIT", 78 | "optional": true, 79 | "os": [ 80 | "android" 81 | ] 82 | }, 83 | "node_modules/@rollup/rollup-android-arm64": { 84 | "version": "4.37.0", 85 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", 86 | "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", 87 | "cpu": [ 88 | "arm64" 89 | ], 90 | "dev": true, 91 | "license": "MIT", 92 | "optional": true, 93 | "os": [ 94 | "android" 95 | ] 96 | }, 97 | "node_modules/@rollup/rollup-darwin-arm64": { 98 | "version": "4.37.0", 99 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", 100 | "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", 101 | "cpu": [ 102 | "arm64" 103 | ], 104 | "dev": true, 105 | "license": "MIT", 106 | "optional": true, 107 | "os": [ 108 | "darwin" 109 | ] 110 | }, 111 | "node_modules/@rollup/rollup-darwin-x64": { 112 | "version": "4.37.0", 113 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", 114 | "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", 115 | "cpu": [ 116 | "x64" 117 | ], 118 | "dev": true, 119 | "license": "MIT", 120 | "optional": true, 121 | "os": [ 122 | "darwin" 123 | ] 124 | }, 125 | "node_modules/@rollup/rollup-freebsd-arm64": { 126 | "version": "4.37.0", 127 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", 128 | "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", 129 | "cpu": [ 130 | "arm64" 131 | ], 132 | "dev": true, 133 | "license": "MIT", 134 | "optional": true, 135 | "os": [ 136 | "freebsd" 137 | ] 138 | }, 139 | "node_modules/@rollup/rollup-freebsd-x64": { 140 | "version": "4.37.0", 141 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", 142 | "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", 143 | "cpu": [ 144 | "x64" 145 | ], 146 | "dev": true, 147 | "license": "MIT", 148 | "optional": true, 149 | "os": [ 150 | "freebsd" 151 | ] 152 | }, 153 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 154 | "version": "4.37.0", 155 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", 156 | "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", 157 | "cpu": [ 158 | "arm" 159 | ], 160 | "dev": true, 161 | "license": "MIT", 162 | "optional": true, 163 | "os": [ 164 | "linux" 165 | ] 166 | }, 167 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 168 | "version": "4.37.0", 169 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", 170 | "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", 171 | "cpu": [ 172 | "arm" 173 | ], 174 | "dev": true, 175 | "license": "MIT", 176 | "optional": true, 177 | "os": [ 178 | "linux" 179 | ] 180 | }, 181 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 182 | "version": "4.37.0", 183 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", 184 | "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", 185 | "cpu": [ 186 | "arm64" 187 | ], 188 | "dev": true, 189 | "license": "MIT", 190 | "optional": true, 191 | "os": [ 192 | "linux" 193 | ] 194 | }, 195 | "node_modules/@rollup/rollup-linux-arm64-musl": { 196 | "version": "4.37.0", 197 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", 198 | "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", 199 | "cpu": [ 200 | "arm64" 201 | ], 202 | "dev": true, 203 | "license": "MIT", 204 | "optional": true, 205 | "os": [ 206 | "linux" 207 | ] 208 | }, 209 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 210 | "version": "4.37.0", 211 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", 212 | "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", 213 | "cpu": [ 214 | "loong64" 215 | ], 216 | "dev": true, 217 | "license": "MIT", 218 | "optional": true, 219 | "os": [ 220 | "linux" 221 | ] 222 | }, 223 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 224 | "version": "4.37.0", 225 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", 226 | "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", 227 | "cpu": [ 228 | "ppc64" 229 | ], 230 | "dev": true, 231 | "license": "MIT", 232 | "optional": true, 233 | "os": [ 234 | "linux" 235 | ] 236 | }, 237 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 238 | "version": "4.37.0", 239 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", 240 | "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", 241 | "cpu": [ 242 | "riscv64" 243 | ], 244 | "dev": true, 245 | "license": "MIT", 246 | "optional": true, 247 | "os": [ 248 | "linux" 249 | ] 250 | }, 251 | "node_modules/@rollup/rollup-linux-riscv64-musl": { 252 | "version": "4.37.0", 253 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", 254 | "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", 255 | "cpu": [ 256 | "riscv64" 257 | ], 258 | "dev": true, 259 | "license": "MIT", 260 | "optional": true, 261 | "os": [ 262 | "linux" 263 | ] 264 | }, 265 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 266 | "version": "4.37.0", 267 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", 268 | "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", 269 | "cpu": [ 270 | "s390x" 271 | ], 272 | "dev": true, 273 | "license": "MIT", 274 | "optional": true, 275 | "os": [ 276 | "linux" 277 | ] 278 | }, 279 | "node_modules/@rollup/rollup-linux-x64-gnu": { 280 | "version": "4.37.0", 281 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", 282 | "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", 283 | "cpu": [ 284 | "x64" 285 | ], 286 | "dev": true, 287 | "license": "MIT", 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ] 292 | }, 293 | "node_modules/@rollup/rollup-linux-x64-musl": { 294 | "version": "4.37.0", 295 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", 296 | "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", 297 | "cpu": [ 298 | "x64" 299 | ], 300 | "dev": true, 301 | "license": "MIT", 302 | "optional": true, 303 | "os": [ 304 | "linux" 305 | ] 306 | }, 307 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 308 | "version": "4.37.0", 309 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", 310 | "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", 311 | "cpu": [ 312 | "arm64" 313 | ], 314 | "dev": true, 315 | "license": "MIT", 316 | "optional": true, 317 | "os": [ 318 | "win32" 319 | ] 320 | }, 321 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 322 | "version": "4.37.0", 323 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", 324 | "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", 325 | "cpu": [ 326 | "ia32" 327 | ], 328 | "dev": true, 329 | "license": "MIT", 330 | "optional": true, 331 | "os": [ 332 | "win32" 333 | ] 334 | }, 335 | "node_modules/@rollup/rollup-win32-x64-msvc": { 336 | "version": "4.37.0", 337 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", 338 | "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", 339 | "cpu": [ 340 | "x64" 341 | ], 342 | "dev": true, 343 | "license": "MIT", 344 | "optional": true, 345 | "os": [ 346 | "win32" 347 | ] 348 | }, 349 | "node_modules/@types/estree": { 350 | "version": "1.0.7", 351 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", 352 | "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", 353 | "dev": true, 354 | "license": "MIT" 355 | }, 356 | "node_modules/@types/node": { 357 | "version": "16.18.126", 358 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", 359 | "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", 360 | "dev": true, 361 | "license": "MIT" 362 | }, 363 | "node_modules/estree-walker": { 364 | "version": "2.0.2", 365 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 366 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 367 | "dev": true, 368 | "license": "MIT" 369 | }, 370 | "node_modules/fsevents": { 371 | "version": "2.3.3", 372 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 373 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 374 | "dev": true, 375 | "hasInstallScript": true, 376 | "license": "MIT", 377 | "optional": true, 378 | "os": [ 379 | "darwin" 380 | ], 381 | "engines": { 382 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 383 | } 384 | }, 385 | "node_modules/function-bind": { 386 | "version": "1.1.2", 387 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 388 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 389 | "dev": true, 390 | "license": "MIT", 391 | "funding": { 392 | "url": "https://github.com/sponsors/ljharb" 393 | } 394 | }, 395 | "node_modules/hasown": { 396 | "version": "2.0.2", 397 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 398 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 399 | "dev": true, 400 | "license": "MIT", 401 | "dependencies": { 402 | "function-bind": "^1.1.2" 403 | }, 404 | "engines": { 405 | "node": ">= 0.4" 406 | } 407 | }, 408 | "node_modules/is-core-module": { 409 | "version": "2.16.1", 410 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", 411 | "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", 412 | "dev": true, 413 | "license": "MIT", 414 | "dependencies": { 415 | "hasown": "^2.0.2" 416 | }, 417 | "engines": { 418 | "node": ">= 0.4" 419 | }, 420 | "funding": { 421 | "url": "https://github.com/sponsors/ljharb" 422 | } 423 | }, 424 | "node_modules/path-parse": { 425 | "version": "1.0.7", 426 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 427 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 428 | "dev": true, 429 | "license": "MIT" 430 | }, 431 | "node_modules/picomatch": { 432 | "version": "4.0.2", 433 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", 434 | "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", 435 | "dev": true, 436 | "license": "MIT", 437 | "engines": { 438 | "node": ">=12" 439 | }, 440 | "funding": { 441 | "url": "https://github.com/sponsors/jonschlinkert" 442 | } 443 | }, 444 | "node_modules/resolve": { 445 | "version": "1.22.10", 446 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", 447 | "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", 448 | "dev": true, 449 | "license": "MIT", 450 | "dependencies": { 451 | "is-core-module": "^2.16.0", 452 | "path-parse": "^1.0.7", 453 | "supports-preserve-symlinks-flag": "^1.0.0" 454 | }, 455 | "bin": { 456 | "resolve": "bin/resolve" 457 | }, 458 | "engines": { 459 | "node": ">= 0.4" 460 | }, 461 | "funding": { 462 | "url": "https://github.com/sponsors/ljharb" 463 | } 464 | }, 465 | "node_modules/rollup": { 466 | "version": "4.37.0", 467 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", 468 | "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", 469 | "dev": true, 470 | "license": "MIT", 471 | "dependencies": { 472 | "@types/estree": "1.0.6" 473 | }, 474 | "bin": { 475 | "rollup": "dist/bin/rollup" 476 | }, 477 | "engines": { 478 | "node": ">=18.0.0", 479 | "npm": ">=8.0.0" 480 | }, 481 | "optionalDependencies": { 482 | "@rollup/rollup-android-arm-eabi": "4.37.0", 483 | "@rollup/rollup-android-arm64": "4.37.0", 484 | "@rollup/rollup-darwin-arm64": "4.37.0", 485 | "@rollup/rollup-darwin-x64": "4.37.0", 486 | "@rollup/rollup-freebsd-arm64": "4.37.0", 487 | "@rollup/rollup-freebsd-x64": "4.37.0", 488 | "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", 489 | "@rollup/rollup-linux-arm-musleabihf": "4.37.0", 490 | "@rollup/rollup-linux-arm64-gnu": "4.37.0", 491 | "@rollup/rollup-linux-arm64-musl": "4.37.0", 492 | "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", 493 | "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", 494 | "@rollup/rollup-linux-riscv64-gnu": "4.37.0", 495 | "@rollup/rollup-linux-riscv64-musl": "4.37.0", 496 | "@rollup/rollup-linux-s390x-gnu": "4.37.0", 497 | "@rollup/rollup-linux-x64-gnu": "4.37.0", 498 | "@rollup/rollup-linux-x64-musl": "4.37.0", 499 | "@rollup/rollup-win32-arm64-msvc": "4.37.0", 500 | "@rollup/rollup-win32-ia32-msvc": "4.37.0", 501 | "@rollup/rollup-win32-x64-msvc": "4.37.0", 502 | "fsevents": "~2.3.2" 503 | } 504 | }, 505 | "node_modules/rollup/node_modules/@types/estree": { 506 | "version": "1.0.6", 507 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 508 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 509 | "dev": true, 510 | "license": "MIT" 511 | }, 512 | "node_modules/supports-preserve-symlinks-flag": { 513 | "version": "1.0.0", 514 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 515 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 516 | "dev": true, 517 | "license": "MIT", 518 | "engines": { 519 | "node": ">= 0.4" 520 | }, 521 | "funding": { 522 | "url": "https://github.com/sponsors/ljharb" 523 | } 524 | }, 525 | "node_modules/tslib": { 526 | "version": "2.8.1", 527 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 528 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 529 | "dev": true, 530 | "license": "0BSD" 531 | }, 532 | "node_modules/typescript": { 533 | "version": "5.8.2", 534 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", 535 | "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", 536 | "dev": true, 537 | "license": "Apache-2.0", 538 | "bin": { 539 | "tsc": "bin/tsc", 540 | "tsserver": "bin/tsserver" 541 | }, 542 | "engines": { 543 | "node": ">=14.17" 544 | } 545 | } 546 | } 547 | } 548 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kaitai-struct", 3 | "version": "0.11.0-SNAPSHOT.3", 4 | "description": "Kaitai Struct: runtime library for JavaScript", 5 | "keywords": [ 6 | "binary", 7 | "file", 8 | "forenics", 9 | "format", 10 | "kaitai", 11 | "parsing", 12 | "reverse engineering", 13 | "reversing", 14 | "runtime", 15 | "stream", 16 | "struct", 17 | "structure" 18 | ], 19 | "homepage": "https://github.com/kaitai-io/kaitai_struct_javascript_runtime#readme", 20 | "bugs": { 21 | "url": "https://github.com/kaitai-io/kaitai_struct_javascript_runtime/issues" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/kaitai-io/kaitai_struct_javascript_runtime.git" 26 | }, 27 | "license": "Apache-2.0", 28 | "author": "Kaitai team (https://github.com/orgs/kaitai-io/people) and Ilmari Heikkinen", 29 | "type": "commonjs", 30 | "main": "index.js", 31 | "types": "index.d.ts", 32 | "files": [ 33 | "KaitaiStream.js", 34 | "KaitaiStream.d.ts", 35 | "index.d.ts" 36 | ], 37 | "scripts": { 38 | "build": "rollup -c", 39 | "prepack": "npm run build" 40 | }, 41 | "devDependencies": { 42 | "@rollup/plugin-typescript": "^12.1.2", 43 | "@types/node": "^16.11.11", 44 | "rollup": "^4.35.0", 45 | "tslib": "^2.3.1", 46 | "typescript": "^5.8.2" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript'; 2 | 3 | export default [{ 4 | input: 'KaitaiStream.ts', 5 | output: { 6 | dir: '.', 7 | format: 'umd', 8 | name: 'KaitaiStream' 9 | }, 10 | plugins: [typescript()] 11 | }]; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "libReplacement": true, /* Enable lib replacement. */ 18 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 19 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 20 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 21 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 22 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 23 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 24 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 25 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 26 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 27 | 28 | /* Modules */ 29 | "module": "es2015", /* Specify what module code is generated. */ 30 | // "rootDir": "./", /* Specify the root folder within your source files. */ 31 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 32 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 33 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 34 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 35 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 36 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 37 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 38 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 39 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 40 | // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ 41 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 42 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 43 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 44 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ 45 | // "resolveJsonModule": true, /* Enable importing .json files. */ 46 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 47 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 48 | 49 | /* JavaScript Support */ 50 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 51 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 52 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 53 | 54 | /* Emit */ 55 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 56 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 57 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 58 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 59 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 62 | "outDir": "./", /* Specify an output folder for all emitted files. */ 63 | // "removeComments": true, /* Disable emitting comments. */ 64 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 65 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 66 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 67 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 68 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 69 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 70 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 71 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 72 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 73 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 74 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 75 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 76 | 77 | /* Interop Constraints */ 78 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 79 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 80 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 81 | // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ 82 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 83 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 84 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 85 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 86 | 87 | /* Type Checking */ 88 | "strict": true, /* Enable all strict type-checking options. */ 89 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 90 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 91 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 92 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 93 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 94 | // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ 95 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 96 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 97 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 98 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 99 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 100 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 101 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 102 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 103 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 104 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 105 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 106 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 107 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 108 | 109 | /* Completeness */ 110 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 111 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 112 | }, 113 | "exclude": [] 114 | } 115 | --------------------------------------------------------------------------------