From 8e959426e25ed8e411332d2d10e14e49b90977ed Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Mon, 15 Sep 2014 13:58:24 -0700 Subject: [PATCH] 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. --- lib/bufferreader.js | 7 ++++++- test/bufferreader.js | 13 +++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/bufferreader.js b/lib/bufferreader.js index 15369fb..27fa495 100644 --- a/lib/bufferreader.js +++ b/lib/bufferreader.js @@ -87,7 +87,12 @@ BufferReader.prototype.readVarInt = function() { case 0xFE: return this.readUInt32LE(); case 0xFF: - throw new Error('number too large to retain precision - use readVarIntBN'); + 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'); default: return first; } diff --git a/test/bufferreader.js b/test/bufferreader.js index 3bbce17..670f9d6 100644 --- a/test/bufferreader.js +++ b/test/bufferreader.js @@ -1,6 +1,7 @@ var BufferWriter = require('../lib/bufferwriter'); var BufferReader = require('../lib/bufferreader'); var should = require('chai').should(); +var BN = require('../lib/bn'); describe('BufferReader', function() { @@ -188,14 +189,22 @@ describe('BufferReader', function() { br.readVarInt().should.equal(50000); }); - it('should throw an error on a 9 byte varint', function() { - var buf = Buffer.concat([new Buffer([255]), new Buffer('ffffffffffffffff', 'hex')]); + it('should throw an error on a 9 byte varint over the javascript uint precision limit', function() { + var buf = BufferWriter().writeVarIntBN(BN(Math.pow(2, 54).toString())).concat(); var br = new BufferReader({buf: buf}); (function() { br.readVarInt(); }).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() {