JS: Support for more types in serializedtypes.js.

This commit is contained in:
Stefan Thomas
2013-02-08 03:16:42 +01:00
parent 3fff761a1e
commit d81ce99d8a
2 changed files with 116 additions and 42 deletions

View File

@@ -92,7 +92,7 @@ SerializedObject.prototype.serialize_field = function (spec, obj)
Type = spec.shift();
if ("undefined" !== typeof obj[name]) {
console.log(name, Type.id, field_id);
//console.log(name, Type.id, field_id);
this.append(SerializedObject.get_field_header(Type.id, field_id));
try {

View File

@@ -12,7 +12,8 @@ var extend = require('extend'),
var amount = require('./amount'),
UInt160 = amount.UInt160,
Amount = amount.Amount;
Amount = amount.Amount,
Currency= amount.Currency;
// Shortcuts
var hex = sjcl.codec.hex,
@@ -47,7 +48,7 @@ SerializedType.prototype.serialize_varint = function (so, val) {
} else throw new Error("Variable integer overflow.");
};
exports.Int8 = new SerializedType({
var STInt8 = exports.Int8 = new SerializedType({
serialize: function (so, val) {
so.append([val & 0xff]);
},
@@ -56,7 +57,7 @@ exports.Int8 = new SerializedType({
}
});
exports.Int16 = new SerializedType({
var STInt16 = exports.Int16 = new SerializedType({
serialize: function (so, val) {
so.append([
val >>> 8 & 0xff,
@@ -65,10 +66,11 @@ exports.Int16 = new SerializedType({
},
parse: function (so) {
// XXX
throw new Error("Parsing Int16 not implemented");
}
});
exports.Int32 = new SerializedType({
var STInt32 = exports.Int32 = new SerializedType({
serialize: function (so, val) {
so.append([
val >>> 24 & 0xff,
@@ -79,46 +81,82 @@ exports.Int32 = new SerializedType({
},
parse: function (so) {
// XXX
throw new Error("Parsing Int32 not implemented");
}
});
exports.Int64 = new SerializedType({
var STInt64 = exports.Int64 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Int64 not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Int64 not implemented");
}
});
exports.Hash128 = new SerializedType({
var STHash128 = exports.Hash128 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Hash128 not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Hash128 not implemented");
}
});
exports.Hash256 = new SerializedType({
var STHash256 = exports.Hash256 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Hash256 not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Hash256 not implemented");
}
});
exports.Hash160 = new SerializedType({
var STHash160 = exports.Hash160 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Hash160 not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Hash160 not implemented");
}
});
exports.Amount = new SerializedType({
// Internal
var STCurrency = new SerializedType({
serialize: function (so, val) {
var currency = val.to_json();
if ("string" === typeof currency && currency.length === 3) {
var currencyCode = currency.toUpperCase(),
currencyData = utils.arraySet(20, 0);
if (!/^[A-Z]{3}$/.test(currencyCode)) {
throw new Error('Invalid currency code');
}
currencyData[12] = currencyCode.charCodeAt(0) & 0xff;
currencyData[13] = currencyCode.charCodeAt(1) & 0xff;
currencyData[14] = currencyCode.charCodeAt(2) & 0xff;
so.append(currencyData);
} else {
throw new Error('Tried to serialize invalid/unimplemented currency type.');
}
},
parse: function (so) {
// XXX
throw new Error("Parsing Currency not implemented");
}
});
var STAmount = exports.Amount = new SerializedType({
serialize: function (so, val) {
var amount = Amount.from_json(val);
if (!amount.is_valid()) {
@@ -126,6 +164,7 @@ exports.Amount = new SerializedType({
}
// Amount (64-bit integer)
var valueBytes = utils.arraySet(8, 0);
if (amount.is_native()) {
var valueHex = amount._value.toString(16);
@@ -137,103 +176,138 @@ exports.Amount = new SerializedType({
valueHex = "0" + valueHex;
}
var valueBytes = bytes.fromBits(hex.toBits(valueHex));
valueBytes = bytes.fromBits(hex.toBits(valueHex));
// Clear most significant two bits - these bits should already be 0 if
// Amount enforces the range correctly, but we'll clear them anyway just
// so this code can make certain guarantees about the encoded value.
valueBytes[0] &= 0x3f;
if (!amount.is_negative()) valueBytes[0] |= 0x40;
so.append(valueBytes);
} else {
// XXX
throw new Error("Non-native amounts not implemented!");
var hi = 0, lo = 0;
// First bit: non-native
hi |= 1 << 31;
if (!amount.is_zero()) {
// Second bit: non-negative?
if (!amount.is_negative()) hi |= 1 << 30;
// Next eight bits: offset/exponent
hi |= ((97 + amount._offset) & 0xff) << 22;
// Remaining 52 bits: mantissa
hi |= amount._value.shiftRight(32).intValue() & 0x3fffff;
lo = amount._value.intValue() & 0xffffffff;
}
valueBytes = sjcl.codec.bytes.fromBits([hi, lo]);
}
so.append(valueBytes);
if (!amount.is_native()) {
// Currency (160-bit hash)
var currency = amount.currency().to_json();
if ("string" === typeof currency && currency.length === 3) {
var currencyCode = currency.toUpperCase(),
currencyData = utils.arraySet(20, 0);
if (!/^[A-Z]{3}$/.test(currencyCode)) {
throw new Error('Invalid currency code');
}
currencyData[12] = currencyCode.charCodeAt(0) & 0xff;
currencyData[13] = currencyCode.charCodeAt(1) & 0xff;
currencyData[14] = currencyCode.charCodeAt(2) & 0xff;
var currencyBits = bytes.toBits(currencyData),
currencyHash = sjcl.hash.ripemd160.hash(currencyBits);
so.append(bytes.fromBits(currencyHash));
} else {
throw new Error('Tried to serialize invalid/unimplemented currency type.');
}
var currency = amount.currency();
STCurrency.serialize(so, currency);
// Issuer (160-bit hash)
// XXX
so.append(amount.issuer().to_bytes());
}
},
parse: function (so) {
// XXX
throw new Error("Parsing Amount not implemented");
}
});
exports.VariableLength = new SerializedType({
var STVL = exports.VariableLength = new SerializedType({
serialize: function (so, val) {
if ("string" === typeof val) this.serialize_hex(so, val);
else throw new Error("Unknown datatype.");
},
parse: function (so) {
// XXX
throw new Error("Parsing VL not implemented");
}
});
exports.Account = new SerializedType({
var STAccount = exports.Account = new SerializedType({
serialize: function (so, val) {
var account = UInt160.from_json(val);
this.serialize_hex(so, account.to_hex());
},
parse: function (so) {
// XXX
throw new Error("Parsing Account not implemented");
}
});
exports.PathSet = new SerializedType({
var STPathSet = exports.PathSet = new SerializedType({
serialize: function (so, val) {
// XXX
for (var i = 0, l = val.length; i < l; i++) {
for (var j = 0, l2 = val[i].length; j < l2; j++) {
var entry = val[i][j];
var type = 0;
if (entry.account) type |= 0x01;
if (entry.currency) type |= 0x10;
if (entry.issuer) type |= 0x20;
STInt8.serialize(so, type);
if (entry.account) {
so.append(UInt160.from_json(entry.account).to_bytes());
}
if (entry.currency) {
var currency = Currency.from_json(entry.currency);
STCurrency.serialize(so, currency);
}
if (entry.issuer) {
so.append(UInt160.from_json(entry.issuer).to_bytes());
}
}
if (j < l2) STInt8.serialize(so, 0xff);
}
STInt8.serialize(so, 0x00);
},
parse: function (so) {
// XXX
throw new Error("Parsing PathSet not implemented");
}
});
exports.Vector256 = new SerializedType({
var STVector256 = exports.Vector256 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Vector256 not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Vector256 not implemented");
}
});
exports.Object = new SerializedType({
var STObject = exports.Object = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Object not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Object not implemented");
}
});
exports.Array = new SerializedType({
var STArray = exports.Array = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Array not implemented");
},
parse: function (so) {
// XXX
throw new Error("Parsing Array not implemented");
}
});