Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions lib/binary_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,30 @@ export class Parser {
return ctx;
}

private nextNotBit() {
// Used to test if next type is a bitN or not
if (this.next) {
if (this.next.type === "nest") {
// For now consider a nest as a bit
if (this.next.options && this.next.options.type instanceof Parser) {
// Something in the nest
if (this.next.options.type.next) {
return this.next.options.type.next.type !== "bit";
}
return false;
} else {
// Nest is empty. For now assume this means bit is not next. However what if something comes after the nest?
return true;
}
} else {
return this.next.type !== "bit";
}
} else {
// Nothing else so next can't be bits
return true;
}
}

private generateBit(ctx: Context) {
// TODO find better method to handle nested bit fields
const parser = JSON.parse(JSON.stringify(this));
Expand All @@ -1047,10 +1071,7 @@ export class Parser {
parser.varName = ctx.generateVariable(parser.varName);
ctx.bitFields.push(parser);

if (
!this.next ||
(this.next && ["bit", "nest"].indexOf(this.next.type) < 0)
) {
if (!this.next || this.nextNotBit()) {
const val = ctx.generateTmpVariable();

ctx.pushCode(`var ${val} = 0;`);
Expand Down
50 changes: 50 additions & 0 deletions test/composite_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,56 @@ function compositeParserTests(
},
});
});

it("standalone bit fields should work", () => {
const parser = Parser.start().bit6("one").bit8("two");
const buffer = factory([0xa8, 0x78]);
const result = parser.parse(buffer);
deepStrictEqual(result.one, 0xa8 >> 2);
deepStrictEqual(result.two, 0x78 >> 2);
});

it("bit to nested bit should work", () => {
const parser = Parser.start()
.bit6("one")
.nest("nested", {
type: new Parser().bit8("two").uint8("three"),
});
const buffer = factory([0xa8, 0x78, 0x45]);
const result = parser.parse(buffer);
deepStrictEqual(result.one, 0xa8 >> 2);
deepStrictEqual(result.nested.two, 0x78 >> 2);
// switching to uint8 should start at next byte (skipping two bits here)
deepStrictEqual(result.nested.three, 0x45);
});

it("bit before nest should work", () => {
const parser = Parser.start()
.useContextVars()
.bit8("items")
.nest("data", {
type: Parser.start()
.uint8("length")
.string("message", { length: "length" })
.array("value", {
type: "uint8",
length: "$parent.items",
}),
});

const buffer = factory([
0x2, 0xc, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
0x6c, 0x64, 0x01, 0x02, 0x02, 0x02,
]);
deepStrictEqual(parser.parse(buffer), {
items: 2,
data: {
length: 12,
message: "hello, world",
value: [0x01, 0x02],
},
});
});
});

describe("Constructors", () => {
Expand Down