Skip to content

Commit a3a6cf8

Browse files
committed
Update to merge PR keichi#18 from @NotBobTheBuilder
2 parents 6f66bf2 + 3819684 commit a3a6cf8

9 files changed

+1219
-1516
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,21 @@ var parser = new Parser()
381381
.int32("c");
382382
```
383383

384+
### setEncoderOptions(opts)
385+
Set specific options for encoding.
386+
Current supported `opts` object may contain:
387+
- bitEndianess: true|false (default false) When true, tell the encoder to respect endianess BITs order, so that
388+
encoding is exactly the reverse of the parsing process for bits fields.
389+
390+
```javascript
391+
var parser = new Parser()
392+
.endianess("little")
393+
.setEncoderOpts({bitEndianess: true}) // Use BITs endianess for bits fields
394+
.bit4("a")
395+
.bit4("b")
396+
.uint16("c");
397+
```
398+
384399
### namely(alias)
385400
Set an alias to this parser, so there will be an opportunity to refer to it by
386401
name in methods like `.array`, `.nest` and `.choice`, instead of requirement

lib/binary_parser.ts

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ interface ParserOptions {
3131
offset?: number | string | ((item: any) => number);
3232
}
3333

34+
interface EncoderOptions {
35+
bitEndianess?: boolean;
36+
}
37+
3438
type Types = PrimitiveTypes | ComplexTypes;
3539

3640
type ComplexTypes =
@@ -175,12 +179,16 @@ export class Parser {
175179
constructorFn: Function | null = null;
176180
alias: string | null = null;
177181
smartBufferSize: number;
182+
encoderOpts: EncoderOptions;
178183

179184
constructor(opts?: any) {
180185
this.smartBufferSize =
181186
opts && typeof opts === 'object' && opts.smartBufferSize
182187
? opts.smartBufferSize
183188
: 256;
189+
this.encoderOpts = {
190+
bitEndianess: false,
191+
};
184192
}
185193

186194
static start(opts?: any) {
@@ -200,7 +208,7 @@ export class Parser {
200208
const typeName = CAPITILIZED_TYPE_NAMES[type];
201209

202210
ctx.pushCode(
203-
`smartBuffer.write${typeName}(${ctx.generateVariable(this.varName)});`,
211+
`smartBuffer.write${typeName}(${ctx.generateVariable(this.varName)});`
204212
);
205213
}
206214

@@ -268,9 +276,7 @@ export class Parser {
268276
const [major] = process.version.replace('v', '').split('.');
269277
if (Number(major) < 12) {
270278
throw new Error(
271-
`The methods readBigInt64BE, readBigInt64BE, readBigInt64BE, readBigInt64BE are not avilable in your version of nodejs: ${
272-
process.version
273-
}, you must use v12 or greater`
279+
`The methods readBigInt64BE, readBigInt64BE, readBigInt64BE, readBigInt64BE are not avilable in your version of nodejs: ${process.version}, you must use v12 or greater`
274280
);
275281
}
276282
}
@@ -590,6 +596,11 @@ export class Parser {
590596
return this;
591597
}
592598

599+
encoderSetOptions(opts: EncoderOptions) {
600+
Object.assign(this.encoderOpts, opts);
601+
return this;
602+
}
603+
593604
create(constructorFn: Function) {
594605
if (!(constructorFn instanceof Function)) {
595606
throw new Error('Constructor must be a Function object.');
@@ -658,8 +669,7 @@ export class Parser {
658669
private addRawCodeEncode(ctx: Context) {
659670
ctx.pushCode('var vars = obj;');
660671
ctx.pushCode(
661-
`var smartBuffer = SmartBuffer.fromOptions({size: ${
662-
this.smartBufferSize}, encoding: "utf8"});`
672+
`var smartBuffer = SmartBuffer.fromOptions({size: ${this.smartBufferSize}, encoding: "utf8"});`
663673
);
664674

665675
this.generateEncode(ctx);
@@ -694,8 +704,7 @@ export class Parser {
694704

695705
ctx.pushCode('var vars = obj;');
696706
ctx.pushCode(
697-
`var smartBuffer = SmartBuffer.fromOptions({size: ${
698-
this.smartBufferSize}, encoding: "utf8"});`
707+
`var smartBuffer = SmartBuffer.fromOptions({size: ${this.smartBufferSize}, encoding: "utf8"});`
699708
);
700709

701710
this.generateEncode(ctx);
@@ -808,6 +817,7 @@ export class Parser {
808817
parser.varName = varName;
809818
parser.options = options || parser.options;
810819
parser.endian = this.endian;
820+
parser.encoderOpts = this.encoderOpts;
811821

812822
if (this.head) {
813823
this.head.next = parser;
@@ -1083,14 +1093,25 @@ export class Parser {
10831093
);
10841094
}
10851095

1086-
1096+
const isBitLittleEndian =
1097+
this.endian === 'le' && this.encoderOpts.bitEndianess;
10871098
const tmpVal = ctx.generateTmpVariable();
1099+
const boundVal = ctx.generateTmpVariable();
10881100
ctx.pushCode(`var ${tmpVal} = 0;`);
1101+
ctx.pushCode(`var ${boundVal} = 0;`);
10891102
let bitOffset = 0;
10901103
ctx.bitFields.forEach(parser => {
10911104
ctx.pushCode(
1092-
`${tmpVal} |= (${parser.varName} << ${
1093-
sum - (parser.options.length as number) - bitOffset});`
1105+
`${boundVal} = (${parser.varName} & ${(1 <<
1106+
(parser.options.length as number)) -
1107+
1});`
1108+
);
1109+
ctx.pushCode(
1110+
`${tmpVal} |= (${boundVal} << ${
1111+
isBitLittleEndian
1112+
? bitOffset
1113+
: sum - (parser.options.length as number) - bitOffset
1114+
});`
10941115
);
10951116
ctx.pushCode(`${tmpVal} = ${tmpVal} >>> 0;`);
10961117
bitOffset += parser.options.length as number;
@@ -1206,7 +1227,7 @@ export class Parser {
12061227
}
12071228
} else {
12081229
ctx.pushCode(
1209-
`smartBuffer.writeString(${name}, "${this.options.encoding}");`,
1230+
`smartBuffer.writeString(${name}, "${this.options.encoding}");`
12101231
);
12111232
}
12121233
if (this.options.zeroTerminated) {
@@ -1342,15 +1363,16 @@ export class Parser {
13421363
// Compute the desired count of array items to encode (min of array size
13431364
// and length option)
13441365
if (length !== undefined) {
1345-
ctx.pushCode(`${maxItems} = ${maxItems} > ${length} ? ${length} : ${maxItems}`);
1366+
ctx.pushCode(
1367+
`${maxItems} = ${maxItems} > ${length} ? ${length} : ${maxItems}`
1368+
);
13461369
}
13471370

13481371
// Save current encoding smartBuffer and allocate a new one
13491372
const savSmartBuffer = ctx.generateTmpVariable();
13501373
ctx.pushCode(
13511374
`var ${savSmartBuffer} = smartBuffer; ` +
1352-
`smartBuffer = SmartBuffer.fromOptions({size: ${
1353-
this.smartBufferSize}, encoding: "utf8"});`,
1375+
`smartBuffer = SmartBuffer.fromOptions({size: ${this.smartBufferSize}, encoding: "utf8"});`
13541376
);
13551377

13561378
ctx.pushCode(`if(${maxItems} > 0) {`);
@@ -1370,7 +1392,9 @@ export class Parser {
13701392

13711393
if (typeof type === 'string') {
13721394
if (!aliasRegistry[type]) {
1373-
ctx.pushCode(`smartBuffer.write${CAPITILIZED_TYPE_NAMES[type as Types]}(${item});`);
1395+
ctx.pushCode(
1396+
`smartBuffer.write${CAPITILIZED_TYPE_NAMES[type as Types]}(${item});`
1397+
);
13741398
} else {
13751399
ctx.pushCode(
13761400
`smartBuffer.writeBuffer(${FUNCTION_ENCODE_PREFIX + type}(${item}));`
@@ -1389,13 +1413,11 @@ export class Parser {
13891413

13901414
if (typeof this.options.encodeUntil === 'function') {
13911415
ctx.pushCode(
1392-
` while (${itemCounter} < ${maxItems} && !(${
1393-
this.options.encodeUntil}).call(this, ${item}, vars));`
1416+
` while (${itemCounter} < ${maxItems} && !(${this.options.encodeUntil}).call(this, ${item}, vars));`
13941417
);
13951418
} else if (typeof this.options.readUntil === 'function') {
13961419
ctx.pushCode(
1397-
` while (${itemCounter} < ${maxItems} && !(${
1398-
this.options.readUntil}).call(this, ${item}, ${savSmartBuffer}.toBuffer()));`
1420+
` while (${itemCounter} < ${maxItems} && !(${this.options.readUntil}).call(this, ${item}, ${savSmartBuffer}.toBuffer()));`
13991421
);
14001422
}
14011423
ctx.pushCode('}'); // End of 'if(...) {'
@@ -1446,14 +1468,15 @@ export class Parser {
14461468
if (typeof type === 'string') {
14471469
if (!aliasRegistry[type]) {
14481470
ctx.pushCode(
1449-
`smartBuffer.write${CAPITILIZED_TYPE_NAMES[type as Types]}(${
1450-
ctx.generateVariable(this.varName)});`
1471+
`smartBuffer.write${
1472+
CAPITILIZED_TYPE_NAMES[type as Types]
1473+
}(${ctx.generateVariable(this.varName)});`
14511474
);
14521475
} else {
14531476
const tempVar = ctx.generateTmpVariable();
14541477
ctx.pushCode(
1455-
`var ${tempVar} = ${FUNCTION_ENCODE_PREFIX + type}(${
1456-
ctx.generateVariable(this.varName)});`
1478+
`var ${tempVar} = ${FUNCTION_ENCODE_PREFIX +
1479+
type}(${ctx.generateVariable(this.varName)});`
14571480
);
14581481
ctx.pushCode(`smartBuffer.writeBuffer(${tempVar});`);
14591482
if (type !== this.alias) ctx.addReference(type);
@@ -1542,7 +1565,8 @@ export class Parser {
15421565
} else if (aliasRegistry[this.options.type]) {
15431566
var tempVar = ctx.generateTmpVariable();
15441567
ctx.pushCode(
1545-
`var ${tempVar} = ${FUNCTION_ENCODE_PREFIX + this.options.type}(${nestVar});`,
1568+
`var ${tempVar} = ${FUNCTION_ENCODE_PREFIX +
1569+
this.options.type}(${nestVar});`
15461570
);
15471571
ctx.pushCode(`smartBuffer.writeBuffer(${tempVar});`);
15481572
if (this.options.type !== this.alias) {
@@ -1557,15 +1581,13 @@ export class Parser {
15571581
formatter: Function
15581582
) {
15591583
if (typeof formatter === 'function') {
1560-
ctx.pushCode(`${varName} = (${formatter}).call(this, ${varName}, buffer, offset);`);
1584+
ctx.pushCode(
1585+
`${varName} = (${formatter}).call(this, ${varName}, buffer, offset);`
1586+
);
15611587
}
15621588
}
15631589

1564-
private generateEncoder(
1565-
ctx: Context,
1566-
varName: string,
1567-
encoder?: Function
1568-
) {
1590+
private generateEncoder(ctx: Context, varName: string, encoder?: Function) {
15691591
if (typeof encoder === 'function') {
15701592
ctx.pushCode(`${varName} = (${encoder}).call(this, ${varName}, vars);`);
15711593
}

0 commit comments

Comments
 (0)