diff --git a/src/implementation/c/node/consume.ts b/src/implementation/c/node/consume.ts index fb37bfe..658a00e 100644 --- a/src/implementation/c/node/consume.ts +++ b/src/implementation/c/node/consume.ts @@ -8,12 +8,31 @@ export class Consume extends Node { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); + const ty = ctx.getFieldType(this.ref.field); + + let fieldTy: string; + if (ty === 'i64') { + fieldTy = 'uint64_t'; + } else if (ty === 'i32') { + fieldTy = 'uint32_t'; + } else if (ty === 'i16') { + fieldTy = 'uint16_t'; + } else if (ty === 'i8') { + fieldTy = 'uint8_t'; + } else { + throw new Error( + `Unsupported type ${ty} of field ${this.ref.field} for consume node`); + } out.push('size_t avail;'); - out.push('size_t need;'); + out.push(`${fieldTy} need;`); + out.push(''); out.push(`avail = ${ctx.endPosArg()} - ${ctx.posArg()};`); out.push(`need = ${index};`); + + // Note: `avail` or `need` are going to coerced to the largest + // datatype needed to hold either of the values. out.push('if (avail >= need) {'); out.push(` p += need;`); out.push(` ${index} = 0;`); diff --git a/test/consume-test.ts b/test/consume-test.ts index faf16ee..f9fb383 100644 --- a/test/consume-test.ts +++ b/test/consume-test.ts @@ -46,4 +46,24 @@ describe('llparse/consume', () => { const binary = await build(p, start, 'consume-i64'); await binary.check('3aaa2bb1a01b', 'off=4\noff=7\noff=9\noff=10\noff=12\n'); }); + + it('should consume bytes with untruncated i64 field', async () => { + p.property('i64', 'to_consume'); + + const start = p.node('start'); + const consume = p.consume('to_consume'); + + start + .select( + NUM_SELECT, + p.invoke(p.code.mulAdd('to_consume', { base: 10 }), start) + ) + .skipTo(consume); + + consume + .otherwise(printOff(p, start)); + + const binary = await build(p, start, 'consume-untruncated-i64'); + await binary.check('4294967297.xxxxxxxx', '\n'); + }); });