Skip to content

Commit 45a1b6e

Browse files
authored
Merge pull request #241 from nick-hunter/bit-to-nest-bugfix
Don't assume nest contains a bit field
2 parents c51a131 + d8f1a31 commit 45a1b6e

2 files changed

Lines changed: 75 additions & 4 deletions

File tree

lib/binary_parser.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,30 @@ export class Parser {
10381038
return ctx;
10391039
}
10401040

1041+
private nextNotBit() {
1042+
// Used to test if next type is a bitN or not
1043+
if (this.next) {
1044+
if (this.next.type === "nest") {
1045+
// For now consider a nest as a bit
1046+
if (this.next.options && this.next.options.type instanceof Parser) {
1047+
// Something in the nest
1048+
if (this.next.options.type.next) {
1049+
return this.next.options.type.next.type !== "bit";
1050+
}
1051+
return false;
1052+
} else {
1053+
// Nest is empty. For now assume this means bit is not next. However what if something comes after the nest?
1054+
return true;
1055+
}
1056+
} else {
1057+
return this.next.type !== "bit";
1058+
}
1059+
} else {
1060+
// Nothing else so next can't be bits
1061+
return true;
1062+
}
1063+
}
1064+
10411065
private generateBit(ctx: Context) {
10421066
// TODO find better method to handle nested bit fields
10431067
const parser = JSON.parse(JSON.stringify(this));
@@ -1047,10 +1071,7 @@ export class Parser {
10471071
parser.varName = ctx.generateVariable(parser.varName);
10481072
ctx.bitFields.push(parser);
10491073

1050-
if (
1051-
!this.next ||
1052-
(this.next && ["bit", "nest"].indexOf(this.next.type) < 0)
1053-
) {
1074+
if (!this.next || this.nextNotBit()) {
10541075
const val = ctx.generateTmpVariable();
10551076

10561077
ctx.pushCode(`var ${val} = 0;`);

test/composite_parser.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,56 @@ function compositeParserTests(
982982
},
983983
});
984984
});
985+
986+
it("standalone bit fields should work", () => {
987+
const parser = Parser.start().bit6("one").bit8("two");
988+
const buffer = factory([0xa8, 0x78]);
989+
const result = parser.parse(buffer);
990+
deepStrictEqual(result.one, 0xa8 >> 2);
991+
deepStrictEqual(result.two, 0x78 >> 2);
992+
});
993+
994+
it("bit to nested bit should work", () => {
995+
const parser = Parser.start()
996+
.bit6("one")
997+
.nest("nested", {
998+
type: new Parser().bit8("two").uint8("three"),
999+
});
1000+
const buffer = factory([0xa8, 0x78, 0x45]);
1001+
const result = parser.parse(buffer);
1002+
deepStrictEqual(result.one, 0xa8 >> 2);
1003+
deepStrictEqual(result.nested.two, 0x78 >> 2);
1004+
// switching to uint8 should start at next byte (skipping two bits here)
1005+
deepStrictEqual(result.nested.three, 0x45);
1006+
});
1007+
1008+
it("bit before nest should work", () => {
1009+
const parser = Parser.start()
1010+
.useContextVars()
1011+
.bit8("items")
1012+
.nest("data", {
1013+
type: Parser.start()
1014+
.uint8("length")
1015+
.string("message", { length: "length" })
1016+
.array("value", {
1017+
type: "uint8",
1018+
length: "$parent.items",
1019+
}),
1020+
});
1021+
1022+
const buffer = factory([
1023+
0x2, 0xc, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
1024+
0x6c, 0x64, 0x01, 0x02, 0x02, 0x02,
1025+
]);
1026+
deepStrictEqual(parser.parse(buffer), {
1027+
items: 2,
1028+
data: {
1029+
length: 12,
1030+
message: "hello, world",
1031+
value: [0x01, 0x02],
1032+
},
1033+
});
1034+
});
9851035
});
9861036

9871037
describe("Constructors", () => {

0 commit comments

Comments
 (0)