Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse order is wrong with bit fields followed by nest #240

Open
nick-hunter opened this issue Jun 16, 2023 · 0 comments
Open

Parse order is wrong with bit fields followed by nest #240

nick-hunter opened this issue Jun 16, 2023 · 0 comments

Comments

@nick-hunter
Copy link
Contributor

I've been debugging some more dynamically generated parsers. After learning about the differences of bit8 and uint8 from issue #239 I switched some of uint8 to bit8 for sections where I'm not sure everything is byte aligned. I found some very unexpected behavior. See example below:

import { Parser } from "binary-parser";

const body = Buffer.from("082F00000682A20A70050E32", "hex");

const incorrect = new Parser()
    .endianness("big")
    .bit8("RATE")
    .bit8("FIELD")
    .nest("TIME", {
        type: new Parser().uint32("coarse").bit24("fine")
    })
// Result { TIME: { coarse: 137297920, fine: 10619504 }, RATE: 6, FIELD: 130 }

const correct = new Parser()
    .endianness("big")
    .uint8("RATE")
    .uint8("FIELD")
    .nest("TIME", {
        type: new Parser().uint32("coarse").bit24("fine")
    })
// Result { RATE: 8, FIELD: 47, TIME: { coarse: 1666, fine: 10619504 } }

Looking at the parser code you can see that the nested code is output before the bits.

Incorrect:

var dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);
var offset = 0;
var vars = {};
vars.$parent = null;
vars.$root = vars;
vars.TIME = {};
vars.TIME.coarse = dataView.getUint32(offset, false);
offset += 4;
var $tmp0 = 0;
$tmp0 = dataView.getUint16(offset);
offset += 2;
vars.RATE = $tmp0 >> 8 & 0xff;
vars.FIELD = $tmp0 >> 0 & 0xff;
$tmp0 = (dataView.getUint16(offset) << 8) | dataView.getUint8(offset + 2);
offset += 3;
vars.TIME.fine = $tmp0 >> 0 & 0xffffff;
delete vars.$parent;
delete vars.$root;
return vars;

Correct:

var dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);
var offset = 0;
var vars = {};
vars.$parent = null;
vars.$root = vars;
vars.RATE = dataView.getUint8(offset, false);
offset += 1;
vars.FIELD = dataView.getUint8(offset, false);
offset += 1;
vars.TIME = {};
vars.TIME.coarse = dataView.getUint32(offset, false);
offset += 4;
var $tmp0 = 0;
$tmp0 = (dataView.getUint16(offset) << 8) | dataView.getUint8(offset + 2);
offset += 3;
vars.TIME.fine = $tmp0 >> 0 & 0xffffff;
delete vars.$parent;
delete vars.$root;
return vars;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant