var base58 = require('../lib/Base58').base58Check; // Constructor. Takes the following forms: // new EncodedData() // new EncodedData() // new EncodedData(, ) // new EncodedData(, <20-byte-hash>) function EncodedData(data, encoding) { this.data = data; if (!encoding && (typeof data == 'string')) { encoding = 'base58'; this.converters = this.encodings[encoding].converters; this._encoding = this.encodings[encoding]._encoding; } else { if (typeof this.encodings[encoding] === 'undefined') encoding = 'binary'; this.converters = this.encodings[encoding].converters; this._encoding = this.encodings[encoding]._encoding; } }; // get or set the encoding used (transforms data) EncodedData.prototype.encoding = function(encoding) { if (encoding && (encoding != this._encoding)) { this.data = this.as(encoding); this.converters = this.encodings[encoding].converters; this._encoding = this.encodings[encoding]._encoding; } return this._encoding; }; // answer a new instance having the given encoding EncodedData.prototype.withEncoding = function(encoding) { return new EncodedData(this.as(encoding), encoding); }; // answer the data in the given encoding EncodedData.prototype.as = function(encoding) { if (!encodings[encoding]) throw new Error('invalid encoding: '+encoding); return this.converters[encoding].call(this); }; // validate that we can convert to binary EncodedData.prototype._validate = function() { this.withEncoding('binary'); }; // Boolean protocol for testing if valid EncodedData.prototype.isValid = function() { try { this.validate(); return true; } catch (e) { return false; } }; // subclasses can override to do more stuff EncodedData.prototype.validate = function() { this._validate(); }; // convert to a string (in base58 form) EncodedData.prototype.toString = function() { return this.as('base58'); }; // utility EncodedData.prototype.doAsBinary = function(callback) { var oldEncoding = this.encoding(); this.encoding('binary'); callback.apply(this); this.encoding(oldEncoding); }; // Setup support for various address encodings. The object for // each encoding inherits from the EncodedData prototype. This // allows any encoding to override any method...changing the encoding // for an instance will change the encoding it inherits from. Note, // this will present some problems for anyone wanting to inherit from // EncodedData (we'll deal with that when needed). var encodings = { 'binary': { converters: { 'binary': function() { var answer = new Buffer(this.data.length); this.data.copy(answer); return answer; }, 'base58': function() { return base58.encode(this.data); }, 'hex': function() { return this.data.toString('hex'); }, }, _validate: function() { //nothing to do here...we make no assumptions about the data }, }, 'base58': { converters: { 'binary': function() { return base58.decode(this.data); }, 'hex': function() { return this.withEncoding('binary').as('hex'); }, }, }, 'hex': { converters: { 'binary': function() { return new Buffer(this.data, 'hex'); }, 'base58': function() { return this.withEncoding('binary').as('base58'); }, }, }, }; var no_conversion = function() { return this.data; }; for (var k in encodings) { if (encodings.hasOwnProperty(k)) { if (!encodings[k].converters[k]) encodings[k].converters[k] = no_conversion; encodings[k]._encoding = k; } } EncodedData.applyEncodingsTo = function(aClass) { var tmp = {}; for (var k in encodings) { var enc = encodings[k]; var obj = Object.create(aClass.prototype); for (var j in enc) { obj[j] = enc[j]; } tmp[k] = obj; } aClass.prototype.encodings = tmp; }; EncodedData.applyEncodingsTo(EncodedData); module.exports = EncodedData;