Skip to content

Instantly share code, notes, and snippets.

@generalmimon
Created April 13, 2022 20:59
Show Gist options
  • Save generalmimon/866bd57f98c227bcbba1e9834e225072 to your computer and use it in GitHub Desktop.
Save generalmimon/866bd57f98c227bcbba1e9834e225072 to your computer and use it in GitHub Desktop.
/**
* SPDX-FileCopyrightText: 2022 Petr Pucil <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
"use strict";
// Base `readBitsIntLe` implemenation: https://github.com/kaitai-io/kaitai_struct_javascript_runtime/blob/abf5542/KaitaiStream.js#L486-L525
// Diff between `readBitsIntLe` and `readBitsIntLeV2` is as follows:
/*
--- 1/readBitsIntLe.js
+++ 2/readBitsIntLeV2.js
@@ -1,4 +1,4 @@
-KaitaiStream.prototype.readBitsIntLe = function(n) {
+KaitaiStream.prototype.readBitsIntLeV2 = function(n) {
// JS only supports bit operations on 32 bits
if (n > 32) {
throw new RangeError("readBitsIntLe: the maximum supported bit length is 32 (tried to read " + n + " bits)");
@@ -11,9 +11,21 @@ KaitaiStream.prototype.readBitsIntLe = function(n) {
// 8 bits => 1 byte
// 9 bits => 2 bytes
var bytesNeeded = ((bitsNeeded - 1) >> 3) + 1; // `ceil(bitsNeeded / 8)` (NB: `x >> 3` is `floor(x / 8)`)
- var buf = this.readBytes(bytesNeeded);
- for (var i = 0; i < bytesNeeded; i++) {
- res |= buf[i] << (i * 8);
+ var shift = 0;
+ switch (bytesNeeded) {
+ case 4:
+ res = this.readU4le();
+ break;
+ case 3:
+ res = this.readU1();
+ shift = 8;
+ // fallthrough
+ case 2:
+ res |= this.readU2le() << shift;
+ break;
+ case 1:
+ res = this.readU1();
+ break;
}
// NB: in JavaScript, bit shift operators always shift by modulo 32 of the right-hand operand (see
*/
const KaitaiStream = require('./KaitaiStream');
const b = require('benny');
const randomData = Uint8Array.from(new Array(24), v => (Math.random() * 0x1_00) >>> 0);
const _io = new KaitaiStream(randomData);
const funcRef = KaitaiStream.prototype.readBitsIntLe.bind(_io);
const funcV2 = KaitaiStream.prototype.readBitsIntLeV2.bind(_io);
function benchIter(io, func) {
io.seek(0);
io.alignToByte();
const rand = (Math.random() * 0x1_0000_0000) >>> 0;
const a = func(1 + (rand & 0b11111));
const b = func(1 + ((rand & 0b11111_00000) >>> 5));
const c = func(1 + ((rand & 0b11111_00000_00000) >>> 10));
const d = func(1 + ((rand & 0b11111_00000_00000_00000) >>> 15));
const e = func(1 + ((rand & 0b11111_00000_00000_00000_00000) >>> 20));
const f = func(1 + ((rand & 0b11111_00000_00000_00000_00000_00000) >>> 25));
}
function run() {
return b.suite(
'readBitsIntLe suite',
b.add('KaitaiStream#readBitsIntLe', benchIter.bind(null, _io, funcRef)),
b.add('KaitaiStream#readBitsIntLeV2', benchIter.bind(null, _io, funcV2)),
b.cycle(),
b.complete(),
);
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment