Browse Source

support reading varInt nums up to js precision

Javascript only supports 64 bit floating points, which have uint precision up
to Math.pow(2, 53). We now support reading variable sized numbers up to that
size. If the number is bigger than that, then we need to use BN.
patch-2
Ryan X. Charles 10 years ago
parent
commit
8e959426e2
  1. 5
      lib/bufferreader.js
  2. 13
      test/bufferreader.js

5
lib/bufferreader.js

@ -87,6 +87,11 @@ BufferReader.prototype.readVarInt = function() {
case 0xFE: case 0xFE:
return this.readUInt32LE(); return this.readUInt32LE();
case 0xFF: case 0xFF:
var bn = this.readUInt64LEBN();
var n = bn.toNumber();
if (n <= Math.pow(2, 53))
return n;
else
throw new Error('number too large to retain precision - use readVarIntBN'); throw new Error('number too large to retain precision - use readVarIntBN');
default: default:
return first; return first;

13
test/bufferreader.js

@ -1,6 +1,7 @@
var BufferWriter = require('../lib/bufferwriter'); var BufferWriter = require('../lib/bufferwriter');
var BufferReader = require('../lib/bufferreader'); var BufferReader = require('../lib/bufferreader');
var should = require('chai').should(); var should = require('chai').should();
var BN = require('../lib/bn');
describe('BufferReader', function() { describe('BufferReader', function() {
@ -188,14 +189,22 @@ describe('BufferReader', function() {
br.readVarInt().should.equal(50000); br.readVarInt().should.equal(50000);
}); });
it('should throw an error on a 9 byte varint', function() { it('should throw an error on a 9 byte varint over the javascript uint precision limit', function() {
var buf = Buffer.concat([new Buffer([255]), new Buffer('ffffffffffffffff', 'hex')]); var buf = BufferWriter().writeVarIntBN(BN(Math.pow(2, 54).toString())).concat();
var br = new BufferReader({buf: buf}); var br = new BufferReader({buf: buf});
(function() { (function() {
br.readVarInt(); br.readVarInt();
}).should.throw('number too large to retain precision - use readVarIntBN'); }).should.throw('number too large to retain precision - use readVarIntBN');
}); });
it('should not throw an error on a 9 byte varint not over the javascript uint precision limit', function() {
var buf = BufferWriter().writeVarIntBN(BN(Math.pow(2, 53).toString())).concat();
var br = new BufferReader({buf: buf});
(function() {
br.readVarInt();
}).should.not.throw('number too large to retain precision - use readVarIntBN');
});
}); });
describe('#readVarIntBN', function() { describe('#readVarIntBN', function() {

Loading…
Cancel
Save