@@ -645,6 +645,39 @@ class KaitaiStream {
645645 return res >>> 0 ;
646646 }
647647
648+ /**
649+ * @param n The number of bits to read.
650+ * @returns The read bits as a {@link BigInt}.
651+ */
652+ public readBitsIntBeAsBigInt ( n : number ) : bigint {
653+ let res = BigInt ( 0 ) ;
654+
655+ const bitsNeeded = n - this . bitsLeft ;
656+ this . bitsLeft = - bitsNeeded & 7 ; // `-bitsNeeded mod 8`
657+
658+ if ( bitsNeeded > 0 ) {
659+ // 1 bit => 1 byte
660+ // 8 bits => 1 byte
661+ // 9 bits => 2 bytes
662+ const bytesNeeded = ( ( bitsNeeded - 1 ) >> 3 ) + 1 ; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`)
663+ const buf = this . mapUint8Array ( bytesNeeded ) ;
664+ for ( let i = 0 ; i < bytesNeeded ; i ++ ) {
665+ res = res << BigInt ( 8 ) | BigInt ( buf [ i ] ) ;
666+ }
667+
668+ const newBits = Number ( res & BigInt ( 0x7f ) ) ;
669+ res = res >> BigInt ( this . bitsLeft ) | BigInt ( this . bits ) << BigInt ( bitsNeeded ) ;
670+ this . bits = newBits ; // will be masked at the end of the function
671+ } else {
672+ res = BigInt ( this . bits >>> - bitsNeeded ) ; // shift unneeded bits out
673+ }
674+
675+ const mask = ( 1 << this . bitsLeft ) - 1 ; // `bitsLeft` is in range 0..7
676+ this . bits &= mask ;
677+
678+ return res ;
679+ }
680+
648681 /**
649682 * Unused since Kaitai Struct Compiler v0.9+ - compatibility with older versions.
650683 *
@@ -675,8 +708,8 @@ class KaitaiStream {
675708 // 9 bits => 2 bytes
676709 const bytesNeeded = ( ( bitsNeeded - 1 ) >> 3 ) + 1 ; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`)
677710 const buf = this . mapUint8Array ( bytesNeeded ) ;
678- for ( let i = 0 ; i < bytesNeeded ; i ++ ) {
679- res |= buf [ i ] << ( i * 8 ) ;
711+ for ( let i = bytesNeeded - 1 ; i >= 0 ; i -- ) {
712+ res = res << 8 | buf [ i ] ;
680713 }
681714
682715 // NB: in JavaScript, bit shift operators always shift by modulo 32 of the right-hand operand (see
@@ -702,6 +735,37 @@ class KaitaiStream {
702735 return res ;
703736 }
704737
738+ /**
739+ * @param n The number of bits to read.
740+ * @returns The read bits as a {@link BigInt}.
741+ * @throws {RangeError }
742+ */
743+ public readBitsIntLeAsBigInt ( n : number ) : bigint {
744+ let res = BigInt ( 0 ) ;
745+ const bitsNeeded = n - this . bitsLeft ;
746+
747+ if ( bitsNeeded > 0 ) {
748+ // 1 bit => 1 byte
749+ // 8 bits => 1 byte
750+ // 9 bits => 2 bytes
751+ const bytesNeeded = ( ( bitsNeeded - 1 ) >> 3 ) + 1 ; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`)
752+ const buf = this . mapUint8Array ( bytesNeeded ) ;
753+ for ( let i = bytesNeeded - 1 ; i >= 0 ; i -- ) {
754+ res = res << BigInt ( 8 ) | BigInt ( buf [ i ] ) ;
755+ }
756+
757+ const newBits = res >> BigInt ( bitsNeeded ) ;
758+ res = ( res << BigInt ( this . bitsLeft ) ) | BigInt ( this . bits ) ;
759+ this . bits = Number ( newBits ) ; // `newBits` is at most 7 bits wide => safe to convert
760+ } else {
761+ res = BigInt ( this . bits ) ;
762+ this . bits >>>= n ;
763+ }
764+
765+ this . bitsLeft = - bitsNeeded & 7 ; // `-bitsNeeded mod 8`
766+ return BigInt . asUintN ( n , res ) ;
767+ }
768+
705769 /**
706770 * Native endianness. Either KaitaiStream.BIG_ENDIAN or KaitaiStream.LITTLE_ENDIAN
707771 * depending on the platform endianness.
0 commit comments