Skip to content

Commit 35b17f8

Browse files
committed
Handle 64 bit numbers
1 parent 89ed773 commit 35b17f8

4 files changed

Lines changed: 60 additions & 26 deletions

File tree

compile.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ function compileFieldRead(ctx, field) {
144144
case 'bool': return prefix + 'Boolean' + suffix;
145145
case 'enum':
146146
case 'uint32':
147+
case 'int32': return prefix + 'Varint' + suffix;
147148
case 'uint64':
148-
case 'int32':
149-
case 'int64': return prefix + 'Varint' + suffix;
149+
case 'int64': return prefix + 'Varint64' + suffix;
150150
case 'sint32':
151151
case 'sint64': return prefix + 'SVarint' + suffix;
152152
case 'fixed32': return prefix + 'Fixed32' + suffix;
@@ -178,9 +178,9 @@ function compileFieldWrite(ctx, field, name) {
178178
case 'bool': return prefix + 'Boolean' + postfix;
179179
case 'enum':
180180
case 'uint32':
181+
case 'int32': return prefix + 'Varint' + postfix;
181182
case 'uint64':
182-
case 'int32':
183-
case 'int64': return prefix + 'Varint' + postfix;
183+
case 'int64': return prefix + 'Varint64' + postfix;
184184
case 'sint32':
185185
case 'sint64': return prefix + 'SVarint' + postfix;
186186
case 'fixed32': return prefix + 'Fixed32' + postfix;

index.js

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable new-cap, no-undef */
12
'use strict';
23

34
module.exports = Pbf;
@@ -90,7 +91,7 @@ Pbf.prototype = {
9091
return val;
9192
},
9293

93-
readVarint: function(isSigned) {
94+
readVarint: function(isSigned, is64) {
9495
var buf = this.buf,
9596
val, b;
9697

@@ -100,11 +101,11 @@ Pbf.prototype = {
100101
b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;
101102
b = buf[this.pos]; val |= (b & 0x0f) << 28;
102103

103-
return readVarintRemainder(val, isSigned, this);
104+
return readVarintRemainder(val, isSigned, is64, this);
104105
},
105106

106-
readVarint64: function() { // for compatibility with v2.0.1
107-
return this.readVarint(true);
107+
readVarint64: function(isSigned) {
108+
return this.readVarint(isSigned, true);
108109
},
109110

110111
readSVarint: function() {
@@ -266,7 +267,7 @@ Pbf.prototype = {
266267
val = +val || 0;
267268

268269
if (val > 0xfffffff || val < 0) {
269-
writeBigVarint(val, this);
270+
writeBigVarint(BigInt(val), this);
270271
return;
271272
}
272273

@@ -282,6 +283,24 @@ Pbf.prototype = {
282283
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
283284
},
284285

286+
writeVarint64: function(val) {
287+
val = BigInt(val);
288+
289+
if (val > 0xfffffff || val < 0) {
290+
writeBigVarint(val, this);
291+
return;
292+
}
293+
294+
val = Number(val);
295+
296+
this.realloc(4);
297+
298+
this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
299+
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
300+
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
301+
this.buf[this.pos++] = (val >>> 7) & 0x7f;
302+
},
303+
285304
writeBoolean: function(val) {
286305
this.writeVarint(Boolean(val));
287306
},
@@ -379,6 +398,10 @@ Pbf.prototype = {
379398
this.writeTag(tag, Pbf.Varint);
380399
this.writeVarint(val);
381400
},
401+
writeVarint64Field: function(tag, val) {
402+
this.writeTag(tag, Pbf.Varint);
403+
this.writeVarint64(val);
404+
},
382405
writeSVarintField: function(tag, val) {
383406
this.writeTag(tag, Pbf.Varint);
384407
this.writeSVarint(val);
@@ -400,16 +423,16 @@ Pbf.prototype = {
400423
}
401424
};
402425

403-
function readVarintRemainder(l, s, p) {
426+
function readVarintRemainder(l, s, is64, p) {
404427
var buf = p.buf,
405428
h, b;
406429

407-
b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s);
408-
b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s);
409-
b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);
410-
b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);
411-
b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);
412-
b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);
430+
b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s, is64);
431+
b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s, is64);
432+
b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s, is64);
433+
b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s, is64);
434+
b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s, is64);
435+
b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s, is64);
413436

414437
throw new Error('Expected varint not more than 10 bytes');
415438
}
@@ -419,7 +442,18 @@ function readPackedEnd(pbf) {
419442
pbf.readVarint() + pbf.pos : pbf.pos + 1;
420443
}
421444

422-
function toNum(low, high, isSigned) {
445+
function toNum(low, high, isSigned, is64) {
446+
if (is64) {
447+
var int;
448+
if (isSigned) {
449+
int = BigInt(high) * BigInt(0x100000000) + BigInt(low >>> 0);
450+
return int.toString();
451+
}
452+
453+
int = (BigInt(high >>> 0) * BigInt(0x100000000)) + BigInt(low >>> 0);
454+
return int.toString();
455+
}
456+
423457
if (isSigned) {
424458
return high * 0x100000000 + (low >>> 0);
425459
}
@@ -431,11 +465,11 @@ function writeBigVarint(val, pbf) {
431465
var low, high;
432466

433467
if (val >= 0) {
434-
low = (val % 0x100000000) | 0;
435-
high = (val / 0x100000000) | 0;
468+
low = Number(val % BigInt(0x100000000)) | 0;
469+
high = Number(val / BigInt(0x100000000)) | 0;
436470
} else {
437-
low = ~(-val % 0x100000000);
438-
high = ~(-val / 0x100000000);
471+
low = ~Number(-val % BigInt(0x100000000));
472+
high = ~Number(-val / BigInt(0x100000000));
439473

440474
if (low ^ 0xffffffff) {
441475
low = (low + 1) | 0;

test/compile.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,14 @@ test('handles negative varint', function(t) {
259259

260260
Envelope.write({
261261
int: -5,
262-
long: -10
262+
long: '-10'
263263
}, pbf);
264264

265265
var buf = pbf.finish();
266266
var data = Envelope.read(new Pbf(buf));
267267

268268
t.equals(data.int, -5);
269-
t.equals(data.long, -10);
269+
t.equals(data.long, '-10');
270270

271271
t.end();
272272
});
@@ -278,14 +278,14 @@ test('handles unsigned varint', function(t) {
278278

279279
Envelope.write({
280280
uint: Math.pow(2, 31),
281-
ulong: Math.pow(2, 63)
281+
ulong: '18446744073709551615'
282282
}, pbf);
283283

284284
var buf = pbf.finish();
285285
var data = Envelope.read(new Pbf(buf));
286286

287287
t.equals(data.uint, Math.pow(2, 31));
288-
t.equals(data.ulong, Math.pow(2, 63));
288+
t.equals(data.ulong, '18446744073709551615');
289289

290290
t.end();
291291
});

test/pbf.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ test('readVarint signed', function(t) {
9595
test('readVarint64 (compatibility)', function(t) {
9696
var bytes = [0xc8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01];
9797
var buf = new Pbf(new Buffer(bytes));
98-
t.equal(buf.readVarint64(), -3000);
98+
t.equal(buf.readVarint64(true), '-3000');
9999
t.end();
100100
});
101101

0 commit comments

Comments
 (0)