fix precision error by handling BNs correctly
This commit is contained in:
parent
c22476d809
commit
cde44d689c
|
@ -1,3 +1,5 @@
|
||||||
|
var BN = require('./bn');
|
||||||
|
|
||||||
var BufferReader = function BufferReader(buf, pos) {
|
var BufferReader = function BufferReader(buf, pos) {
|
||||||
if (!(this instanceof BufferReader))
|
if (!(this instanceof BufferReader))
|
||||||
return new BufferReader(buf);
|
return new BufferReader(buf);
|
||||||
|
@ -45,24 +47,19 @@ BufferReader.prototype.readUInt32LE = function() {
|
||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: What if n is so large that it loses precision?
|
BufferReader.prototype.readUInt64BEBN = function() {
|
||||||
BufferReader.prototype.readUInt64BE = function() {
|
var buf = this.buf.slice(this.pos, this.pos + 8);
|
||||||
var val = 0;
|
var bn = BN().fromBuffer(buf);
|
||||||
for (var i = 0; i < 8; i++) {
|
|
||||||
val += Math.pow(256, i) * this.buf[this.pos + 8 - 1 - i];
|
|
||||||
}
|
|
||||||
this.pos = this.pos + 8;
|
this.pos = this.pos + 8;
|
||||||
return val;
|
return bn;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: What if n is so large that it loses precision?
|
BufferReader.prototype.readUInt64LEBN = function() {
|
||||||
BufferReader.prototype.readUInt64LE = function() {
|
var buf = this.buf.slice(this.pos, this.pos + 8);
|
||||||
var val = 0;
|
var reversebuf = BufferReader(buf).reverse().read();
|
||||||
for (var i = 0; i < 8; i++) {
|
var bn = BN().fromBuffer(reversebuf);
|
||||||
val += Math.pow(256, i) * this.buf[this.pos + i];
|
|
||||||
}
|
|
||||||
this.pos = this.pos + 8;
|
this.pos = this.pos + 8;
|
||||||
return val;
|
return bn;
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferReader.prototype.readVarInt = function() {
|
BufferReader.prototype.readVarInt = function() {
|
||||||
|
@ -73,12 +70,26 @@ BufferReader.prototype.readVarInt = function() {
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
return this.readUInt32LE();
|
return this.readUInt32LE();
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
return this.readUInt64LE();
|
return this.readUInt64LEBN().toNumber();
|
||||||
default:
|
default:
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BufferReader.prototype.readVarIntBN = function() {
|
||||||
|
var first = this.readUInt8();
|
||||||
|
switch (first) {
|
||||||
|
case 0xFD:
|
||||||
|
return BN(this.readUInt16LE());
|
||||||
|
case 0xFE:
|
||||||
|
return BN(this.readUInt32LE());
|
||||||
|
case 0xFF:
|
||||||
|
return this.readUInt64LEBN();
|
||||||
|
default:
|
||||||
|
return BN(first);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BufferReader.prototype.reverse = function() {
|
BufferReader.prototype.reverse = function() {
|
||||||
var buf = new Buffer(this.buf.length);
|
var buf = new Buffer(this.buf.length);
|
||||||
for (var i = 0; i < buf.length; i++)
|
for (var i = 0; i < buf.length; i++)
|
||||||
|
|
|
@ -82,33 +82,33 @@ describe('BufferReader', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#readUInt64BE', function() {
|
describe('#readUInt64BEBN', function() {
|
||||||
|
|
||||||
it('should return 1', function() {
|
it('should return 1', function() {
|
||||||
var buf = new Buffer(8);
|
var buf = new Buffer(8);
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
buf.writeUInt32BE(1, 4);
|
buf.writeUInt32BE(1, 4);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64BE().should.equal(1);
|
br.readUInt64BEBN().toNumber().should.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 2^64', function() {
|
it('should return 2^64', function() {
|
||||||
var buf = new Buffer(8);
|
var buf = new Buffer(8);
|
||||||
buf.fill(0xff);
|
buf.fill(0xff);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64BE().should.equal(Math.pow(2, 64));
|
br.readUInt64BEBN().toNumber().should.equal(Math.pow(2, 64));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#readUInt64LE', function() {
|
describe('#readUInt64LEBN', function() {
|
||||||
|
|
||||||
it('should return 1', function() {
|
it('should return 1', function() {
|
||||||
var buf = new Buffer(8);
|
var buf = new Buffer(8);
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
buf.writeUInt32LE(1, 0);
|
buf.writeUInt32LE(1, 0);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64LE().should.equal(1);
|
br.readUInt64LEBN().toNumber().should.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 2^30', function() {
|
it('should return 2^30', function() {
|
||||||
|
@ -116,21 +116,21 @@ describe('BufferReader', function() {
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
buf.writeUInt32LE(Math.pow(2, 30), 0);
|
buf.writeUInt32LE(Math.pow(2, 30), 0);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64LE().should.equal(Math.pow(2, 30));
|
br.readUInt64LEBN().toNumber().should.equal(Math.pow(2, 30));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 0', function() {
|
it('should return 0', function() {
|
||||||
var buf = new Buffer(8);
|
var buf = new Buffer(8);
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64LE().should.equal(0);
|
br.readUInt64LEBN().toNumber().should.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 2^64', function() {
|
it('should return 2^64', function() {
|
||||||
var buf = new Buffer(8);
|
var buf = new Buffer(8);
|
||||||
buf.fill(0xff);
|
buf.fill(0xff);
|
||||||
var br = new BufferReader(buf);
|
var br = new BufferReader(buf);
|
||||||
br.readUInt64LE().should.equal(Math.pow(2, 64));
|
br.readUInt64LEBN().toNumber().should.equal(Math.pow(2, 64));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -164,6 +164,35 @@ describe('BufferReader', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#readVarIntBN', function() {
|
||||||
|
|
||||||
|
it('should read a 1 byte varint', function() {
|
||||||
|
var buf = new Buffer([50]);
|
||||||
|
var br = new BufferReader(buf);
|
||||||
|
br.readVarIntBN().toNumber().should.equal(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read a 3 byte varint', function() {
|
||||||
|
var buf = new Buffer([253, 253, 0]);
|
||||||
|
var br = new BufferReader(buf);
|
||||||
|
br.readVarIntBN().toNumber().should.equal(253);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read a 5 byte varint', function() {
|
||||||
|
var buf = new Buffer([254, 0, 0, 0, 0]);
|
||||||
|
buf.writeUInt32LE(50000, 1);
|
||||||
|
var br = new BufferReader(buf);
|
||||||
|
br.readVarIntBN().toNumber().should.equal(50000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read a 9 byte varint', function() {
|
||||||
|
var buf = Buffer.concat([new Buffer([255]), new Buffer('ffffffffffffffff', 'hex')]);
|
||||||
|
var br = new BufferReader(buf);
|
||||||
|
br.readVarIntBN().toNumber().should.equal(Math.pow(2, 64));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('#reverse', function() {
|
describe('#reverse', function() {
|
||||||
|
|
||||||
it('should reverse this [0, 1]', function() {
|
it('should reverse this [0, 1]', function() {
|
||||||
|
|
Loading…
Reference in New Issue