From 18e38dee2b8629db409bb3efef35d5ead558b843 Mon Sep 17 00:00:00 2001 From: Kagami Hiiragi Date: Thu, 1 Jan 2015 22:26:06 +0300 Subject: [PATCH] Move var_int to core structures module --- lib/address.js | 10 ++--- lib/index.js | 2 + lib/struct.js | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/varint.js | 101 ---------------------------------------------- test.js | 78 +++++++++++++++++------------------ 5 files changed, 154 insertions(+), 144 deletions(-) create mode 100644 lib/struct.js delete mode 100644 lib/varint.js diff --git a/lib/address.js b/lib/address.js index 1bfcd0a..b704b77 100644 --- a/lib/address.js +++ b/lib/address.js @@ -11,7 +11,7 @@ require("object.assign").shim(); var assert = require("assert"); var bufferEqual = require("buffer-equal"); var bs58 = require("bs58"); -var varint = require("./varint"); +var var_int = require("./struct").var_int; var bmcrypto = require("./crypto"); /** @@ -58,11 +58,11 @@ Address.decode = function(str) { return getchecksum(data).then(function(realchecksum) { assert(bufferEqual(checksum, realchecksum), "Bad checkum"); - var decoded = varint.decode(data); + var decoded = var_int.decode(data); var version = decoded.value; data = decoded.rest; - decoded = varint.decode(data); + decoded = var_int.decode(data); var stream = decoded.value; var ripe = decoded.rest; @@ -185,8 +185,8 @@ Address.prototype.encode = function() { var self = this; return self.getRipe({short: true}).then(function(ripe) { var data = Buffer.concat([ - varint.encode(self.version), - varint.encode(self.stream), + var_int.encode(self.version), + var_int.encode(self.stream), ripe, ]); return getchecksum(data).then(function(checksum) { diff --git a/lib/index.js b/lib/index.js index 02ce5bf..87e3cb4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -17,3 +17,5 @@ exports.Int64 = require("int64-native"); exports.Address = require("./address"); /** Working with WIF. */ exports.wif = require("./wif"); +/** Core structures. */ +exports.struct = require("./struct"); diff --git a/lib/struct.js b/lib/struct.js new file mode 100644 index 0000000..5cbce53 --- /dev/null +++ b/lib/struct.js @@ -0,0 +1,107 @@ +/** + * Implements core structures. + * @see {@link https://bitmessage.org/wiki/Protocol_specification#Common_structures} + * @module bitmessage/struct + */ + +"use strict"; + +var assert = require("assert"); +var bitmessage = require("./"); + +/** + * var_int. + * @see {@link https://bitmessage.org/wiki/Protocol_specification#Variable_length_integer} + */ +exports.var_int = { + /** + * Decode var_int. + * @param {Buffer} buf - Buffer that starts with encoded var_int + * @return {{value: (number|Int64), length: number, rest: number}} + * Decoded var_int structure. + */ + decode: function(buf) { + assert(buf.length > 0, "Empty buffer"); + var value, length; + switch (buf[0]) { + case 253: + value = buf.readUInt16BE(1); + assert(value >= 253, "Impractical var_int"); + length = 3; + break; + case 254: + value = buf.readUInt32BE(1); + assert(value >= 65536, "Impractical var_int"); + length = 5; + break; + case 255: + var hi = buf.readUInt32BE(1); + assert(hi !== 0, "Impractical var_int"); + var lo = buf.readUInt32BE(5); + value = new bitmessage.Int64(hi, lo); + length = 9; + break; + default: + value = buf[0]; + length = 1; + } + var rest = buf.slice(length); + return {value: value, length: length, rest: rest}; + }, + + /** + * Encode number into var_int. + * @param {(number|Int64|Buffer)} value - Input number + * @return {Buffer} Encoded var_int. + */ + encode: function(value) { + var buf, buf64, targetStart; + if (typeof value === "number") { + assert(value >= 0, "Value cannot be less than zero"); + if (value < 253) { + buf = new Buffer([value]); + } else if (value < 65536) { + buf = new Buffer(3); + buf[0] = 253; + buf.writeUInt16BE(value, 1); + } else if (value < 4294967296) { + buf = new Buffer(5); + buf[0] = 254; + buf.writeUInt32BE(value, 1); + } else { + // Value may be inaccurate (max safe int = 2^53) but we will still + // try to convert it. + buf = new Buffer(9); + buf[0] = 255; + buf.writeUInt32BE(Math.floor(value / 4294967296), 1); // high32 + buf.writeUInt32BE(value % 4294967296, 5); // low32 + } + } else { + if (value.high32 && value.low32) { + // int64-native instance. + buf = new Buffer(9); + buf[0] = 255; + buf.writeUInt32BE(value.high32(), 1); + buf.writeUInt32BE(value.low32(), 5); + } else { + // Try to convert to buffer. + if (Buffer.isBuffer(value)) { + buf64 = value; + } else if (value.toBuffer) { + // node-int64 instance, rawBuffer = true (prevents extra buffer + // allocation since we copy it's value to new buffer anyway). + buf64 = value.toBuffer(true); + } else { + throw new Error("Value encode error"); + } + assert(buf64.length <= 8, "Buffer too big"); + buf = new Buffer(9); + buf.fill(0); + buf[0] = 255; + targetStart = 1 + (8 - buf64.length); + buf64.copy(buf, targetStart); + } + } + return buf; + }, +}; diff --git a/lib/varint.js b/lib/varint.js deleted file mode 100644 index 755033f..0000000 --- a/lib/varint.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Implements `var_int` encoding/decoding. - * @see {@link https://bitmessage.org/wiki/Protocol_specification#Variable_length_integer} - * @module bitmessage/varint - */ - -"use strict"; - -var assert = require("assert"); -var bitmessage = require("./"); - -/** - * Decode var_int. - * @param {Buffer} buf - Buffer that starts with encoded var_int - * @return {{value: (number|Int64), length: number, rest: number}} - * Decoded var_int structure. - */ -exports.decode = function(buf) { - assert(buf.length > 0, "Empty buffer"); - var value, length; - switch (buf[0]) { - case 253: - value = buf.readUInt16BE(1); - assert(value >= 253, "Impractical var_int"); - length = 3; - break; - case 254: - value = buf.readUInt32BE(1); - assert(value >= 65536, "Impractical var_int"); - length = 5; - break; - case 255: - var hi = buf.readUInt32BE(1); - assert(hi !== 0, "Impractical var_int"); - var lo = buf.readUInt32BE(5); - value = new bitmessage.Int64(hi, lo); - length = 9; - break; - default: - value = buf[0]; - length = 1; - } - var rest = buf.slice(length); - return {value: value, length: length, rest: rest}; -}; - -/** - * Encode number into var_int. - * @param {(number|Int64|Buffer)} value - Input number - * @return {Buffer} Encoded var_int. - */ -exports.encode = function(value) { - var buf, buf64, targetStart; - if (typeof value === "number") { - assert(value >= 0, "Value cannot be less than zero"); - if (value < 253) { - buf = new Buffer([value]); - } else if (value < 65536) { - buf = new Buffer(3); - buf[0] = 253; - buf.writeUInt16BE(value, 1); - } else if (value < 4294967296) { - buf = new Buffer(5); - buf[0] = 254; - buf.writeUInt32BE(value, 1); - } else { - // Value may be inaccurate (max safe int = 2^53) but we will still - // try to convert it. - buf = new Buffer(9); - buf[0] = 255; - buf.writeUInt32BE(Math.floor(value / 4294967296), 1); // high32 - buf.writeUInt32BE(value % 4294967296, 5); // low32 - } - } else { - if (value.high32 && value.low32) { - // int64-native instance. - buf = new Buffer(9); - buf[0] = 255; - buf.writeUInt32BE(value.high32(), 1); - buf.writeUInt32BE(value.low32(), 5); - } else { - // Try to convert to buffer. - if (Buffer.isBuffer(value)) { - buf64 = value; - } else if (value.toBuffer) { - // node-int64 instance, rawBuffer = true (prevents extra buffer - // allocation since we copy it's value to new buffer anyway). - buf64 = value.toBuffer(true); - } else { - throw new Error("Value encode error"); - } - assert(buf64.length <= 8, "Buffer too big"); - buf = new Buffer(9); - buf.fill(0); - buf[0] = 255; - targetStart = 1 + (8 - buf64.length); - buf64.copy(buf, targetStart); - } - } - return buf; -}; diff --git a/test.js b/test.js index 7578e3b..5784f45 100644 --- a/test.js +++ b/test.js @@ -7,52 +7,54 @@ var bitmessage = require("./lib"); var Int64 = bitmessage.Int64; var Address = bitmessage.Address; var wif = bitmessage.wif; -var varint = require("./lib/varint"); +var var_int = bitmessage.struct.var_int; var bmcrypto = require("./lib/crypto"); -describe("var_int", function() { - it("should decode", function() { - var res; - expect(varint.decode.bind(null, Buffer([]))).to.throw(Error); - expect(varint.decode.bind(null, Buffer("fd00", "hex"))).to.throw(Error); +describe("Core structures", function() { + describe("var_int", function() { + it("should decode", function() { + var res; + expect(var_int.decode.bind(null, Buffer([]))).to.throw(Error); + expect(var_int.decode.bind(null, Buffer("fd00", "hex"))).to.throw(Error); - res = varint.decode(Buffer([123])); - expect(res.value).to.equal(123); - expect(res.length).to.equal(1); - expect(res.rest.toString("hex")).to.equal("") + res = var_int.decode(Buffer([123])); + expect(res.value).to.equal(123); + expect(res.length).to.equal(1); + expect(res.rest.toString("hex")).to.equal("") - res = varint.decode(Buffer("fd123456", "hex")); - expect(res.value).to.equal(0x1234); - expect(res.length).to.equal(3); - expect(res.rest.toString("hex")).to.equal("56"); + res = var_int.decode(Buffer("fd123456", "hex")); + expect(res.value).to.equal(0x1234); + expect(res.length).to.equal(3); + expect(res.rest.toString("hex")).to.equal("56"); - res = varint.decode(Buffer("fe1234567890", "hex")); - expect(res.value).to.equal(0x12345678); - expect(res.length).to.equal(5); - expect(res.rest.toString("hex")).to.equal("90"); + res = var_int.decode(Buffer("fe1234567890", "hex")); + expect(res.value).to.equal(0x12345678); + expect(res.length).to.equal(5); + expect(res.rest.toString("hex")).to.equal("90"); - res = varint.decode(Buffer("ff0000001234567890", "hex")); - expect(res.value == 0x1234567890).to.be.true; - expect(res.length).to.equal(9); - expect(res.rest.length).to.equal(0); - }); + res = var_int.decode(Buffer("ff0000001234567890", "hex")); + expect(res.value == 0x1234567890).to.be.true; + expect(res.length).to.equal(9); + expect(res.rest.length).to.equal(0); + }); - it("should check for lowest length on decode", function() { - expect(varint.decode.bind(null, Buffer("fd00fc", "hex"))).to.throw(Error); - expect(varint.decode.bind(null, Buffer("fe0000ffff", "hex"))).to.throw(Error); - expect(varint.decode.bind(null, Buffer("ff00000000ffffffff", "hex"))).to.throw(Error); - }); + it("should check for lowest length on decode", function() { + expect(var_int.decode.bind(null, Buffer("fd00fc", "hex"))).to.throw(Error); + expect(var_int.decode.bind(null, Buffer("fe0000ffff", "hex"))).to.throw(Error); + expect(var_int.decode.bind(null, Buffer("ff00000000ffffffff", "hex"))).to.throw(Error); + }); - it("should encode", function() { - expect(varint.encode(123).toString("hex")).to.equal("7b"); - expect(varint.encode(0x1234).toString("hex")).to.equal("fd1234"); - expect(varint.encode(0x12345678).toString("hex")).to.equal("fe12345678"); - expect(varint.encode(0x1234567890).toString("hex")).to.equal("ff0000001234567890"); - expect(varint.encode(new Int64("0xffffffffffffffff")).toString("hex")).to.equal("ffffffffffffffffff"); - expect(varint.encode(Buffer("1234567890", "hex")).toString("hex")).to.equal("ff0000001234567890"); - expect(varint.encode.bind(null, -123)).to.throw(Error); - expect(varint.encode.bind(null, Buffer("123456789012345678", "hex"))).to.throw(Error); - expect(varint.encode.bind(null, "test")).to.throw(Error); + it("should encode", function() { + expect(var_int.encode(123).toString("hex")).to.equal("7b"); + expect(var_int.encode(0x1234).toString("hex")).to.equal("fd1234"); + expect(var_int.encode(0x12345678).toString("hex")).to.equal("fe12345678"); + expect(var_int.encode(0x1234567890).toString("hex")).to.equal("ff0000001234567890"); + expect(var_int.encode(new Int64("0xffffffffffffffff")).toString("hex")).to.equal("ffffffffffffffffff"); + expect(var_int.encode(Buffer("1234567890", "hex")).toString("hex")).to.equal("ff0000001234567890"); + expect(var_int.encode.bind(null, -123)).to.throw(Error); + expect(var_int.encode.bind(null, Buffer("123456789012345678", "hex"))).to.throw(Error); + expect(var_int.encode.bind(null, "test")).to.throw(Error); + }); }); });