Skip to content

Commit

Permalink
encoding: start using int64 objects instead of BNs.
Browse files Browse the repository at this point in the history
  • Loading branch information
chjj committed Aug 17, 2017
1 parent 411db44 commit 668202b
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 218 deletions.
194 changes: 72 additions & 122 deletions lib/utils/encoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @module utils/encoding
*/

const BN = require('bn.js');
const {U64, I64} = require('./int64');
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
const encoding = exports;

Expand Down Expand Up @@ -443,133 +443,95 @@ encoding.writeI64BE = function writeI64BE(dst, num, off) {
* Read uint64le.
* @param {Buffer} data
* @param {Number} off
* @returns {BN}
* @returns {U64}
*/

encoding.readU64BN = function readU64BN(data, off) {
const num = data.slice(off, off + 8);
return new BN(num, 'le');
encoding.readU64N = function readU64N(data, off) {
return U64.readLE(data, off);
};

/**
* Read uint64be.
* @param {Buffer} data
* @param {Number} off
* @returns {BN}
* @returns {U64}
*/

encoding.readU64BEBN = function readU64BEBN(data, off) {
const num = data.slice(off, off + 8);
return new BN(num, 'be');
encoding.readU64BEN = function readU64BEN(data, off) {
return U64.readBE(data, off);
};

/**
* Read int64le.
* @param {Buffer} data
* @param {Number} off
* @returns {BN}
* @returns {I64}
*/

encoding.readI64BN = function readI64BN(data, off) {
const num = data.slice(off, off + 8);

if (num[num.length - 1] & 0x80)
return new BN(num, 'le').notn(64).addn(1).neg();

return new BN(num, 'le');
encoding.readI64N = function readI64N(data, off) {
return I64.readLE(data, off);
};
/**
* Read int64be.
* @param {Buffer} data
* @param {Number} off
* @returns {BN}
*/

encoding.readI64BEBN = function readI64BEBN(data, off) {
const num = data.slice(off, off + 8);

if (num[0] & 0x80)
return new BN(num, 'be').notn(64).addn(1).neg();

return new BN(num, 'be');
};

/**
* Write int64le.
* @private
* @param {Buffer} dst
* @param {BN} num
* @param {Number} off
* @param {Boolean} be
* @returns {Number} Buffer offset.
* @returns {I64}
*/

encoding._writeI64BN = function _writeI64BN(dst, num, off, be) {
const bits = num.bitLength();

if (bits <= 53)
return encoding._writeI64(dst, num.toNumber(), off, be);

if (bits > 64)
num = num.maskn(64);

if (num.isNeg())
num = num.neg().inotn(64).iaddn(1);

num = num.toArray(be ? 'be' : 'le', 8);

for (let i = 0; i < num.length; i++)
dst[off++] = num[i];

return off;
encoding.readI64BEN = function readI64BEN(data, off) {
return I64.readBE(data, off);
};

/**
* Write uint64le.
* @param {Buffer} dst
* @param {BN} num
* @param {U64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeU64BN = function writeU64BN(dst, num, off) {
return encoding._writeI64BN(dst, num, off, false);
encoding.writeU64N = function writeU64N(dst, num, off) {
enforce(!num.sign, off, 'Signed.');
return num.writeLE(dst, off);
};

/**
* Write uint64be.
* @param {Buffer} dst
* @param {BN} num
* @param {U64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeU64BEBN = function writeU64BEBN(dst, num, off) {
return encoding._writeI64BN(dst, num, off, true);
encoding.writeU64BEN = function writeU64BEN(dst, num, off) {
enforce(!num.sign, off, 'Signed.');
return num.writeBE(dst, off);
};

/**
* Write int64le.
* @param {Buffer} dst
* @param {BN} num
* @param {U64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeI64BN = function writeI64BN(dst, num, off) {
return encoding._writeI64BN(dst, num, off, false);
encoding.writeI64N = function writeI64N(dst, num, off) {
enforce(num.sign, off, 'Not signed.');
return num.writeLE(dst, off);
};

/**
* Write int64be.
* @param {Buffer} dst
* @param {BN} num
* @param {I64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeI64BEBN = function writeI64BEBN(dst, num, off) {
return encoding._writeI64BN(dst, num, off, true);
encoding.writeI64BEN = function writeI64BEN(dst, num, off) {
enforce(num.sign, off, 'Not signed.');
return num.writeBE(dst, off);
};

/**
Expand Down Expand Up @@ -695,54 +657,54 @@ encoding.sizeVarint = function sizeVarint(num) {
* @returns {Object}
*/

encoding.readVarintBN = function readVarintBN(data, off) {
encoding.readVarintN = function readVarintN(data, off) {
assert(off < data.length, off);

switch (data[off]) {
case 0xff: {
const size = 9;
assert(off + size <= data.length, off);
const value = encoding.readU64BN(data, off + 1);
enforce(value.bitLength() > 32, off, 'Non-canonical varint');
return new Varint(size, value);
}
default: {
const result = encoding.readVarint(data, off);
result.value = new BN(result.value);
return result;
}
if (data[off] === 0xff) {
const size = 9;
assert(off + size <= data.length, off);
const value = encoding.readU64N(data, off + 1);
enforce(value.gtn(0xffffffff), off, 'Non-canonical varint');
return new Varint(size, value);
}

const result = encoding.readVarint(data, off);
result.value = U64.fromInt(result.value);
return result;
};

/**
* Write a varint.
* @param {Buffer} dst
* @param {BN} num
* @param {U64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeVarintBN = function writeVarintBN(dst, num, off) {
if (num.bitLength() > 32) {
encoding.writeVarintN = function writeVarintN(dst, num, off) {
enforce(!num.sign, off, 'Signed.');

if (num.gtn(0xffffffff)) {
dst[off++] = 0xff;
off = encoding.writeU64BN(dst, num, off);
return off;
return encoding.writeU64N(dst, num, off);
}

return encoding.writeVarint(dst, num.toNumber(), off);
return encoding.writeVarint(dst, num.toInt(), off);
};

/**
* Calculate size of varint.
* @param {BN} num
* @param {U64} num
* @returns {Number} size
*/

encoding.sizeVarintBN = function sizeVarintBN(num) {
if (num.bitLength() > 32)
encoding.sizeVarintN = function sizeVarintN(num) {
enforce(!num.sign, off, 'Signed.');

if (num.gtn(0xffffffff))
return 9;

return encoding.sizeVarint(num.toNumber());
return encoding.sizeVarint(num.toInt());
};

/**
Expand Down Expand Up @@ -851,34 +813,16 @@ encoding.sizeVarint2 = function sizeVarint2(num) {
* @returns {Object}
*/

encoding.readVarint2BN = function readVarint2BN(data, off) {
let num = 0;
encoding.readVarint2N = function readVarint2N(data, off) {
let num = new U64();
let size = 0;

while (num < 0x3fffffffffff) {
assert(off < data.length, off);

const ch = data[off++];
size++;

num = (num * 0x80) + (ch & 0x7f);

if ((ch & 0x80) === 0)
return new Varint(size, new BN(num));

num++;
}

num = new BN(num);

for (;;) {
assert(off < data.length, off);

const ch = data[off++];
size++;

enforce(num.bitLength() <= 64, off, 'Number exceeds 64 bits');

num.iushln(7).iaddn(ch & 0x7f);

if ((ch & 0x80) === 0)
Expand All @@ -893,21 +837,25 @@ encoding.readVarint2BN = function readVarint2BN(data, off) {
/**
* Write a varint (type 2).
* @param {Buffer} dst
* @param {BN} num
* @param {U64} num
* @param {Number} off
* @returns {Number} Buffer offset.
*/

encoding.writeVarint2BN = function writeVarint2BN(dst, num, off) {
if (num.bitLength() <= 53)
return encoding.writeVarint2(dst, num.toNumber());
encoding.writeVarint2N = function writeVarint2N(dst, num, off) {
enforce(!num.sign, off, 'Signed.');

if (num.hi === 0)
return encoding.writeVarint2(dst, num.toInt(), off);

const tmp = [];
let len = 0;

num = num.clone();

for (;;) {
tmp[len] = (num.words[0] & 0x7f) | (len ? 0x80 : 0x00);
if (num.cmpn(0x7f) <= 0)
tmp[len] = num.andln(0x7f) | (len ? 0x80 : 0x00);
if (num.lten(0x7f))
break;
num.iushrn(7).isubn(1);
len++;
Expand All @@ -924,21 +872,23 @@ encoding.writeVarint2BN = function writeVarint2BN(dst, num, off) {

/**
* Calculate size of varint (type 2).
* @param {BN} num
* @param {U64} num
* @returns {Number} size
*/

encoding.sizeVarint2BN = function sizeVarint2BN(num) {
if (num.bitLength() <= 53)
return encoding.sizeVarint(num.toNumber());
encoding.sizeVarint2N = function sizeVarint2N(num) {
enforce(!num.sign, off, 'Signed.');

if (num.hi === 0)
return encoding.sizeVarint2(num.toInt());

num = num.clone();

let size = 0;

for (;;) {
size++;
if (num.cmpn(0x7f) <= 0)
if (num.lten(0x7f))
break;
num.iushrn(7).isubn(1);
}
Expand Down
Loading

0 comments on commit 668202b

Please sign in to comment.