diff --git a/compile.js b/compile.js index c09ae25..085b5f4 100644 --- a/compile.js +++ b/compile.js @@ -144,9 +144,9 @@ function compileFieldRead(ctx, field) { case 'bool': return prefix + 'Boolean' + suffix; case 'enum': case 'uint32': + case 'int32': return prefix + 'Varint' + suffix; case 'uint64': - case 'int32': - case 'int64': return prefix + 'Varint' + suffix; + case 'int64': return prefix + 'Varint64' + suffix; case 'sint32': case 'sint64': return prefix + 'SVarint' + suffix; case 'fixed32': return prefix + 'Fixed32' + suffix; @@ -178,9 +178,9 @@ function compileFieldWrite(ctx, field, name) { case 'bool': return prefix + 'Boolean' + postfix; case 'enum': case 'uint32': + case 'int32': return prefix + 'Varint' + postfix; case 'uint64': - case 'int32': - case 'int64': return prefix + 'Varint' + postfix; + case 'int64': return prefix + 'Varint64' + postfix; case 'sint32': case 'sint64': return prefix + 'SVarint' + postfix; case 'fixed32': return prefix + 'Fixed32' + postfix; diff --git a/index.js b/index.js index 0bc7405..faa22ae 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ +/* eslint-disable new-cap, no-undef */ 'use strict'; module.exports = Pbf; @@ -90,7 +91,7 @@ Pbf.prototype = { return val; }, - readVarint: function(isSigned) { + readVarint: function(isSigned, is64) { var buf = this.buf, val, b; @@ -100,11 +101,11 @@ Pbf.prototype = { b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val; b = buf[this.pos]; val |= (b & 0x0f) << 28; - return readVarintRemainder(val, isSigned, this); + return readVarintRemainder(val, isSigned, is64, this); }, - readVarint64: function() { // for compatibility with v2.0.1 - return this.readVarint(true); + readVarint64: function(isSigned) { + return this.readVarint(isSigned, true); }, readSVarint: function() { @@ -266,7 +267,7 @@ Pbf.prototype = { val = +val || 0; if (val > 0xfffffff || val < 0) { - writeBigVarint(val, this); + writeBigVarint(BigInt(val), this); return; } @@ -282,6 +283,24 @@ Pbf.prototype = { this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2); }, + writeVarint64: function(val) { + val = BigInt(val); + + if (val > 0xfffffff || val < 0) { + writeBigVarint(val, this); + return; + } + + val = Number(val); + + this.realloc(4); + + this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return; + this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return; + this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return; + this.buf[this.pos++] = (val >>> 7) & 0x7f; + }, + writeBoolean: function(val) { this.writeVarint(Boolean(val)); }, @@ -379,6 +398,10 @@ Pbf.prototype = { this.writeTag(tag, Pbf.Varint); this.writeVarint(val); }, + writeVarint64Field: function(tag, val) { + this.writeTag(tag, Pbf.Varint); + this.writeVarint64(val); + }, writeSVarintField: function(tag, val) { this.writeTag(tag, Pbf.Varint); this.writeSVarint(val); @@ -400,16 +423,16 @@ Pbf.prototype = { } }; -function readVarintRemainder(l, s, p) { +function readVarintRemainder(l, s, is64, p) { var buf = p.buf, h, b; - b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s); - b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s); - b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s); - b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s); - b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s); - b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s); + b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s, is64); + b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s, is64); + b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s, is64); + b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s, is64); + b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s, is64); + b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s, is64); throw new Error('Expected varint not more than 10 bytes'); } @@ -419,7 +442,18 @@ function readPackedEnd(pbf) { pbf.readVarint() + pbf.pos : pbf.pos + 1; } -function toNum(low, high, isSigned) { +function toNum(low, high, isSigned, is64) { + if (is64) { + var int; + if (isSigned) { + int = BigInt(high) * BigInt(0x100000000) + BigInt(low >>> 0); + return int.toString(); + } + + int = (BigInt(high >>> 0) * BigInt(0x100000000)) + BigInt(low >>> 0); + return int.toString(); + } + if (isSigned) { return high * 0x100000000 + (low >>> 0); } @@ -431,11 +465,11 @@ function writeBigVarint(val, pbf) { var low, high; if (val >= 0) { - low = (val % 0x100000000) | 0; - high = (val / 0x100000000) | 0; + low = Number(val % BigInt(0x100000000)) | 0; + high = Number(val / BigInt(0x100000000)) | 0; } else { - low = ~(-val % 0x100000000); - high = ~(-val / 0x100000000); + low = ~Number(-val % BigInt(0x100000000)); + high = ~Number(-val / BigInt(0x100000000)); if (low ^ 0xffffffff) { low = (low + 1) | 0; diff --git a/test/compile.test.js b/test/compile.test.js index 4021bf6..104574c 100644 --- a/test/compile.test.js +++ b/test/compile.test.js @@ -259,14 +259,14 @@ test('handles negative varint', function(t) { Envelope.write({ int: -5, - long: -10 + long: '-10' }, pbf); var buf = pbf.finish(); var data = Envelope.read(new Pbf(buf)); t.equals(data.int, -5); - t.equals(data.long, -10); + t.equals(data.long, '-10'); t.end(); }); @@ -278,14 +278,14 @@ test('handles unsigned varint', function(t) { Envelope.write({ uint: Math.pow(2, 31), - ulong: Math.pow(2, 63) + ulong: '18446744073709551615' }, pbf); var buf = pbf.finish(); var data = Envelope.read(new Pbf(buf)); t.equals(data.uint, Math.pow(2, 31)); - t.equals(data.ulong, Math.pow(2, 63)); + t.equals(data.ulong, '18446744073709551615'); t.end(); }); diff --git a/test/pbf.test.js b/test/pbf.test.js index 3ba6753..9c60dfa 100644 --- a/test/pbf.test.js +++ b/test/pbf.test.js @@ -95,7 +95,7 @@ test('readVarint signed', function(t) { test('readVarint64 (compatibility)', function(t) { var bytes = [0xc8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01]; var buf = new Pbf(new Buffer(bytes)); - t.equal(buf.readVarint64(), -3000); + t.equal(buf.readVarint64(true), '-3000'); t.end(); });