Skip to content

Commit 4d471ce

Browse files
committed
Handle 64 bit numbers
1 parent 89ed773 commit 4d471ce

File tree

5 files changed

+76
-42
lines changed

5 files changed

+76
-42
lines changed

README.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ var data = new Pbf(buffer).readFields(readData, {});
7373

7474
function readData(tag, data, pbf) {
7575
if (tag === 1) data.name = pbf.readString();
76-
else if (tag === 2) data.version = pbf.readVarint();
76+
else if (tag === 2) data.version = pbf.readVarint32();
7777
else if (tag === 3) data.layer = pbf.readMessage(readLayer, {});
7878
}
7979
function readLayer(tag, layer, pbf) {
8080
if (tag === 1) layer.name = pbf.readString();
81-
else if (tag === 3) layer.size = pbf.readVarint();
81+
else if (tag === 3) layer.size = pbf.readVarint32();
8282
}
8383
```
8484

@@ -143,7 +143,7 @@ Read a sequence of fields:
143143

144144
```js
145145
pbf.readFields(function (tag) {
146-
if (tag === 1) pbf.readVarint();
146+
if (tag === 1) pbf.readVarint32();
147147
else if (tag === 2) pbf.readString();
148148
else ...
149149
});
@@ -156,7 +156,7 @@ and also passes the `Pbf` object as a third argument:
156156
var result = pbf.readFields(callback, {})
157157

158158
function callback(tag, result, pbf) {
159-
if (tag === 1) result.id = pbf.readVarint();
159+
if (tag === 1) result.id = pbf.readVarint32();
160160
}
161161
```
162162

@@ -165,9 +165,9 @@ To read an embedded message, use `pbf.readMessage(fn[, obj])` (in the same way a
165165
Read values:
166166

167167
```js
168-
var value = pbf.readVarint();
168+
var value = pbf.readVarint32();
169169
var str = pbf.readString();
170-
var numbers = pbf.readPackedVarint();
170+
var numbers = pbf.readPackedVarint32();
171171
```
172172

173173
For lazy or partial decoding, simply save the position instead of reading a value,
@@ -185,8 +185,8 @@ pbf.readMessage(readFoo);
185185

186186
Scalar reading methods:
187187

188-
* `readVarint(isSigned)` (pass `true` if you expect negative varints)
189-
* `readSVarint()`
188+
* `readVarint32(isSigned)` (pass `true` if you expect negative varints)
189+
* `readSVarint32()`
190190
* `readFixed32()`
191191
* `readFixed64()`
192192
* `readSFixed32()`
@@ -200,8 +200,8 @@ Scalar reading methods:
200200

201201
Packed reading methods:
202202

203-
* `readPackedVarint(arr, isSigned)` (appends read items to `arr`)
204-
* `readPackedSVarint(arr)`
203+
* `readPackedVarint32(arr, isSigned)` (appends read items to `arr`)
204+
* `readPackedSVarint32(arr)`
205205
* `readPackedFixed32(arr)`
206206
* `readPackedFixed64(arr)`
207207
* `readPackedSFixed32(arr)`
@@ -215,7 +215,7 @@ Packed reading methods:
215215
Write values:
216216

217217
```js
218-
pbf.writeVarint(123);
218+
pbf.writeVarint32(123);
219219
pbf.writeString("Hello world");
220220
```
221221

@@ -246,8 +246,8 @@ Field writing methods:
246246

247247
Packed field writing methods:
248248

249-
* `writePackedVarint(tag, val)`
250-
* `writePackedSVarint(tag, val)`
249+
* `writePackedVarint32(tag, val)`
250+
* `writePackedSVarint32(tag, val)`
251251
* `writePackedSFixed32(tag, val)`
252252
* `writePackedSFixed64(tag, val)`
253253
* `writePackedBoolean(tag, val)`
@@ -256,8 +256,8 @@ Packed field writing methods:
256256

257257
Scalar writing methods:
258258

259-
* `writeVarint(val)`
260-
* `writeSVarint(val)`
259+
* `writeVarint32(val)`
260+
* `writeSVarint32(val)`
261261
* `writeSFixed32(val)`
262262
* `writeSFixed64(val)`
263263
* `writeBoolean(val)`
@@ -345,7 +345,7 @@ This release include tons of compatibility/robustness fixes, and a more reliable
345345
- Fixed `writeVarint` to write `0` when given `NaN` or other non-number to avoid producing a broken Protobuf message.
346346
- Changed `readPacked*` methods signature to accept an optional `arr` argument to append the results to (to support messages with repeated fields that mix packed/non-packed encoding).
347347
- Added an optional `isSigned` argument to `readVarint` that enables proper reading of negative varints.
348-
- Deprecated `readVarint64()` (it still works, but it's recommended to be changed to `readVarint(true)`).
348+
- Deprecated `readVarint64()` (it still works, but it's recommended to be changed to `readVarint32(true)`).
349349
- Faster string encoding.
350350

351351
##### Proto compiler

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)