3 changed files with 184 additions and 130 deletions
@ -0,0 +1,136 @@ |
|||||
|
require('classtool'); |
||||
|
|
||||
|
function ClassSpec(b) { |
||||
|
var base58 = b.base58 || require('base58-native').base58Check; |
||||
|
|
||||
|
// Constructor. Takes the following forms:
|
||||
|
// new EncodedData(<base58_address_string>)
|
||||
|
// new EncodedData(<binary_buffer>)
|
||||
|
// new EncodedData(<data>, <encoding>)
|
||||
|
// new EncodedData(<version>, <20-byte-hash>)
|
||||
|
function EncodedData(data, encoding) { |
||||
|
this.data = data; |
||||
|
if(!encoding && (typeof data == 'string')) { |
||||
|
this.__proto__ = this.encodings['base58']; |
||||
|
} else { |
||||
|
this.__proto__ = this.encodings[encoding || 'binary']; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// get or set the encoding used (transforms data)
|
||||
|
EncodedData.prototype.encoding = function(encoding) { |
||||
|
if(encoding && (encoding != this._encoding)) { |
||||
|
this.data = this.as(encoding); |
||||
|
this.__proto__ = this.encodings[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'); |
||||
|
return this.converters[encoding].call(this); |
||||
|
}; |
||||
|
|
||||
|
// validate that we can convert to binary
|
||||
|
EncodedData.prototype._validate = function() { |
||||
|
this.withEncoding('binary'); |
||||
|
}; |
||||
|
|
||||
|
// 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'); |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
for(var k in encodings) { |
||||
|
if(!encodings[k].converters[k]) |
||||
|
encodings[k].converters[k] = function() {return this.data;}; |
||||
|
encodings[k]._encoding = k; |
||||
|
} |
||||
|
|
||||
|
EncodedData.applyEncodingsTo = function(aClass) { |
||||
|
var tmp = {}; |
||||
|
for(var k in encodings) { |
||||
|
var enc = encodings[k]; |
||||
|
var obj = {}; |
||||
|
for(var j in enc) { |
||||
|
obj[j] = enc[j]; |
||||
|
} |
||||
|
obj.__proto__ = aClass.prototype; |
||||
|
tmp[k] = obj; |
||||
|
} |
||||
|
aClass.prototype.encodings = tmp; |
||||
|
}; |
||||
|
|
||||
|
EncodedData.applyEncodingsTo(EncodedData); |
||||
|
return EncodedData; |
||||
|
}; |
||||
|
module.defineClass(ClassSpec); |
@ -0,0 +1,39 @@ |
|||||
|
require('classtool'); |
||||
|
|
||||
|
function ClassSpec(b) { |
||||
|
var superclass = b.superclass || require('./EncodedData').class(); |
||||
|
|
||||
|
function VersionedData(version, payload) { |
||||
|
if(typeof version != 'number') { |
||||
|
VersionedData.super(this, arguments); |
||||
|
return; |
||||
|
}; |
||||
|
this.data = new Buffer(payload.length + 1); |
||||
|
this.__proto__ = this.encodings['binary']; |
||||
|
this.version(version); |
||||
|
this.payload(payload); |
||||
|
}; |
||||
|
VersionedData.superclass = superclass; |
||||
|
superclass.applyEncodingsTo(VersionedData); |
||||
|
|
||||
|
// get or set the version data (the first byte of the address)
|
||||
|
VersionedData.prototype.version = function(num) { |
||||
|
if(num || (num === 0)) { |
||||
|
this.doAsBinary(function() {this.data.writeUInt8(num, 0);}); |
||||
|
return num; |
||||
|
} |
||||
|
return this.as('binary').readUInt8(0); |
||||
|
}; |
||||
|
|
||||
|
// get or set the payload data (as a Buffer object)
|
||||
|
VersionedData.prototype.payload = function(data) { |
||||
|
if(data) { |
||||
|
this.doAsBinary(function() {data.copy(this.data,1);}); |
||||
|
return data; |
||||
|
} |
||||
|
return this.as('binary').slice(1); |
||||
|
}; |
||||
|
|
||||
|
return VersionedData; |
||||
|
}; |
||||
|
module.defineClass(ClassSpec); |
Loading…
Reference in new issue