diff --git a/index.js b/index.js index dbca854..6a28bce 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,8 @@ privsec.Base58 = require('./lib/base58'); privsec.Base58Check = require('./lib/base58check'); privsec.BIP32 = require('./lib/bip32'); privsec.BN = require('./lib/bn'); +privsec.BufferReader = require('./lib/bufferreader'); +privsec.BufferWriter = require('./lib/bufferwriter'); privsec.Constants = require('./lib/constants'); privsec.ECDSA = require('./lib/ecdsa'); privsec.Hash = require('./lib/hash'); diff --git a/lib/bufferwriter.js b/lib/bufferwriter.js new file mode 100644 index 0000000..2082aed --- /dev/null +++ b/lib/bufferwriter.js @@ -0,0 +1,98 @@ +var BufferWriter = function BufferWriter(bufs) { + if (!(this instanceof BufferWriter)) + return new BufferReader(buf); + this.bufs = bufs || []; +}; + +BufferWriter.prototype.concat = function() { + return Buffer.concat(this.bufs); +}; + +BufferWriter.prototype.write = function(buf) { + this.bufs.push(buf); + return this; +}; + +BufferWriter.prototype.writeUInt8 = function(n) { + var buf = new Buffer(1); + buf.writeUInt8(n, 0); + this.write(buf); + return this; +}; + +BufferWriter.prototype.writeUInt16BE = function(n) { + var buf = new Buffer(2); + buf.writeUInt16BE(n, 0); + this.write(buf); + return this; +}; + +BufferWriter.prototype.writeUInt16LE = function(n) { + var buf = new Buffer(2); + buf.writeUInt16LE(n, 0); + this.write(buf); + return this; +}; + +BufferWriter.prototype.writeUInt32BE = function(n) { + var buf = new Buffer(4); + buf.writeUInt32BE(n, 0); + this.write(buf); + return this; +}; + +BufferWriter.prototype.writeUInt32LE = function(n) { + var buf = new Buffer(4); + buf.writeUInt32LE(n, 0); + this.write(buf); + return this; +}; + +//TODO: What if n is so large that it loses precision? +BufferWriter.prototype.writeUInt64BE = function(n) { + var buf = new Buffer(8); + buf.writeInt32BE(n & -1, 4); + buf.writeUInt32BE(Math.floor(n / 0x100000000), 0); + this.write(buf); + return this; +}; + +//TODO: What if n is so large that it loses precision? +BufferWriter.prototype.writeUInt64LE = function(n) { + var buf = new Buffer(8); + buf.writeInt32LE(n & -1, 0); + buf.writeUInt32LE(Math.floor(n / 0x100000000), 4); + this.write(buf); + return this; +}; + +BufferWriter.prototype.writeVarInt = function(n) { + var buf = BufferWriter.varIntBuf(n); + this.write(buf); + return this; +}; + +//TODO: What if n is so large that it loses precision? +BufferWriter.varIntBuf = function(n) { + var buf = undefined; + if (n < 253) { + buf = new Buffer(1); + buf.writeUInt8(n, 0); + } else if (n < 0x10000) { + buf = new Buffer(1 + 2); + buf.writeUInt8(253, 0); + buf.writeUInt16LE(n, 1); + } else if (n < 0x100000000) { + buf = new Buffer(1 + 4); + buf.writeUInt8(254, 0); + buf.writeUInt32LE(n, 1); + } else { + buf = new Buffer(1 + 8); + buf.writeUInt8(255, 0); + buf.writeInt32LE(n & -1, 1); + buf.writeUInt32LE(Math.floor(n / 0x100000000), 5); + } + return buf; +}; + +module.exports = BufferWriter; diff --git a/test/test.bufferwriter.js b/test/test.bufferwriter.js new file mode 100644 index 0000000..05be1f5 --- /dev/null +++ b/test/test.bufferwriter.js @@ -0,0 +1,124 @@ +var BufferWriter = require('../lib/bufferwriter'); +var should = require('chai').should(); + +describe('BufferWriter', function() { + + it('should create a new buffer writer', function() { + var bw = new BufferWriter(); + should.exist(bw); + }); + + describe('#concat', function() { + + it('should concat these two bufs', function() { + var buf1 = new Buffer([0]); + var buf2 = new Buffer([1]); + var bw = new BufferWriter([buf1, buf2]); + bw.concat().toString('hex').should.equal('0001'); + }); + + }); + + describe('#write', function() { + + it('should write a buffer', function() { + var buf = new Buffer([0]); + var bw = new BufferWriter(); + bw.write(buf); + bw.concat().toString('hex').should.equal('00'); + }); + + }); + + describe('#writeUInt8', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt8(1).concat().toString('hex').should.equal('01'); + }); + + }); + + describe('#writeUInt16BE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt16BE(1).concat().toString('hex').should.equal('0001'); + }); + + }); + + describe('#writeUInt16LE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt16LE(1).concat().toString('hex').should.equal('0100'); + }); + + }); + + describe('#writeUInt32BE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt32BE(1).concat().toString('hex').should.equal('00000001'); + }); + + }); + + describe('#writeUInt32LE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt32LE(1).concat().toString('hex').should.equal('01000000'); + }); + + }); + + describe('#writeUInt64BE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt64BE(1).concat().toString('hex').should.equal('0000000000000001'); + }); + + }); + + describe('#writeUInt64LE', function() { + + it('should write 1', function() { + var bw = new BufferWriter(); + bw.writeUInt64LE(1).concat().toString('hex').should.equal('0100000000000000'); + }); + + }); + + describe('#writeVarInt', function() { + + it('should write a 1 byte varInt', function() { + var bw = new BufferWriter(); + bw.writeVarInt(1); + bw.concat().length.should.equal(1); + }); + + it('should write a 3 byte varInt', function() { + var bw = new BufferWriter(); + bw.writeVarInt(1000); + bw.concat().length.should.equal(3); + }); + + it('should write a 5 byte varInt', function() { + var bw = new BufferWriter(); + bw.writeVarInt(Math.pow(2, 16 + 1)); + bw.concat().length.should.equal(5); + }); + + it('should write a 9 byte varInt', function() { + var bw = new BufferWriter(); + bw.writeVarInt(Math.pow(2, 32 + 1)); + bw.concat().length.should.equal(9); + }); + + }); + +});