Skip to content

Commit c0ee310

Browse files
committed
Additional checks to determine if next field is a bit field or not
1 parent c51a131 commit c0ee310

2 files changed

Lines changed: 64 additions & 7 deletions

File tree

lib/binary_parser.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ export class Parser {
286286
alias?: string;
287287
useContextVariables = false;
288288

289-
constructor() {}
289+
constructor() { }
290290

291291
static start() {
292292
return new Parser();
@@ -1038,6 +1038,36 @@ 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+
if (this.next.options.type.next.type === "bit") {
1050+
// Next is a bit field
1051+
return false;
1052+
} else {
1053+
// Next is something elses
1054+
return true;
1055+
}
1056+
}
1057+
return false;
1058+
} else {
1059+
// Nest is empty. For now assume this means bit is not next. However what if something comes after the nest?
1060+
return true;
1061+
}
1062+
} else {
1063+
return this.next.type !== "bit";
1064+
}
1065+
} else {
1066+
// Nothing else so next can't be bits
1067+
return true;
1068+
}
1069+
}
1070+
10411071
private generateBit(ctx: Context) {
10421072
// TODO find better method to handle nested bit fields
10431073
const parser = JSON.parse(JSON.stringify(this));
@@ -1049,7 +1079,7 @@ export class Parser {
10491079

10501080
if (
10511081
!this.next ||
1052-
(this.next && ["bit", "nest"].indexOf(this.next.type) < 0)
1082+
this.nextNotBit()
10531083
) {
10541084
const val = ctx.generateTmpVariable();
10551085

@@ -1097,8 +1127,7 @@ export class Parser {
10971127
if (rem) {
10981128
const mask = -1 >>> (32 - rem);
10991129
ctx.pushCode(
1100-
`${parser.varName} = (${val} & 0x${mask.toString(16)}) << ${
1101-
length - rem
1130+
`${parser.varName} = (${val} & 0x${mask.toString(16)}) << ${length - rem
11021131
};`
11031132
);
11041133
length -= rem;
@@ -1110,8 +1139,7 @@ export class Parser {
11101139
const mask = -1 >>> (32 - length);
11111140

11121141
ctx.pushCode(
1113-
`${parser.varName} ${
1114-
length < (parser.options.length as number) ? "|=" : "="
1142+
`${parser.varName} ${length < (parser.options.length as number) ? "|=" : "="
11151143
} ${val} >> ${offset} & 0x${mask.toString(16)};`
11161144
);
11171145

test/composite_parser.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,35 @@ function compositeParserTests(
982982
},
983983
});
984984
});
985+
986+
it("bit before nest should work", () => {
987+
const parser = Parser.start()
988+
.useContextVars()
989+
.bit8("items")
990+
.nest("data", {
991+
type: Parser.start()
992+
.uint8("length")
993+
.string("message", { length: "length" })
994+
.array("value", {
995+
type: "uint8",
996+
length: "$parent.items",
997+
}),
998+
});
999+
1000+
const buffer = factory([
1001+
0x2, 0xc, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
1002+
0x6c, 0x64, 0x01, 0x02, 0x02, 0x02,
1003+
]);
1004+
deepStrictEqual(parser.parse(buffer), {
1005+
items: 2,
1006+
data: {
1007+
length: 12,
1008+
message: "hello, world",
1009+
value: [0x01, 0x02],
1010+
},
1011+
});
1012+
});
1013+
9851014
});
9861015

9871016
describe("Constructors", () => {
@@ -1044,7 +1073,7 @@ function compositeParserTests(
10441073
});
10451074
});
10461075

1047-
it("should pass variable context to child parser", () => {});
1076+
it("should pass variable context to child parser", () => { });
10481077
const parser = Parser.start()
10491078
.uint16be("len")
10501079
.pointer("child", {

0 commit comments

Comments
 (0)