UNPKG

reign

Version:

A persistent, typed-objects implementation.

338 lines (305 loc) 15.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createInitializeStruct = createInitializeStruct; exports.createStoreStruct = createStoreStruct; exports.createAccepts = createAccepts; exports.createToJSON = createToJSON; exports.createClearStruct = createClearStruct; exports.createStructDestructor = createStructDestructor; exports.createCompareAddresses = createCompareAddresses; exports.createEqual = createEqual; exports.createCompareValues = createCompareValues; exports.createCompareAddressValue = createCompareAddressValue; exports.createHashStruct = createHashStruct; exports.createRandomValue = createRandomValue; exports.isValidIdentifier = isValidIdentifier; var _backing = require("backing"); var _backing2 = _interopRequireDefault(_backing); var _symbols = require("../../symbols"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /** * Creates a function which can initialize a new struct, either * via a config object or by using default (empty) field values. */ function createInitializeStruct(Partial, fields) { var defaults = []; var setValues = fields.map(function (field, index) { var name = field.name; var type = field.type; var offset = field.offset; defaults.push(field.default); if (isValidIdentifier(name)) { return "\n type" + index + ".initialize(backing, address + " + offset + ", (tmp = input." + name + ") !== undefined ? tmp : defaults[" + index + "]());\n "; } else { var sanitizedName = JSON.stringify(name); return "\n type" + index + ".initialize(backing, address + " + offset + ", (tmp = input[" + sanitizedName + "]) !== undefined ? tmp : defaults[" + index + "]());\n "; } }).join(''); var setEmpty = fields.map(function (_ref, index) { var name = _ref.name; var type = _ref.type; var offset = _ref.offset; return "\n type" + index + ".initialize(backing, address + " + offset + ", defaults[" + index + "]());\n "; }).join(''); var argNames = ['$Address', 'Partial', 'defaults'].concat(_toConsumableArray(fields.map(function (_, index) { return "type" + index; }))); var args = [_symbols.$Address, Partial, defaults].concat(_toConsumableArray(fields.map(function (field) { return field.type; }))); var body = "\n \"use strict\";\n return function initializeStruct (backing, address, input) {\n if (input == null) {\n " + setEmpty + "\n }\n else if (input instanceof Partial) {\n backing.copy(address, input[$Address], Partial.byteLength);\n }\n else {\n var tmp;\n " + setValues + "\n }\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Creates a function which can write a struct, either * via a config object or by using default (empty) field values. */ function createStoreStruct(Partial, fields) { var defaults = []; var setValues = fields.map(function (field, index) { var name = field.name; var type = field.type; var offset = field.offset; defaults.push(field.default); if (isValidIdentifier(name)) { return "\n type" + index + ".store(backing, address + " + offset + ", (tmp = input." + name + ") !== undefined ? tmp : defaults[" + index + "]);\n "; } else { var sanitizedName = JSON.stringify(name); return "\n type" + index + ".store(backing, address + " + offset + ", (tmp = input[" + sanitizedName + "]) !== undefined ? tmp : defaults[" + index + "]);\n "; } }).join(''); var setEmpty = fields.map(function (_ref2, index) { var name = _ref2.name; var type = _ref2.type; var offset = _ref2.offset; return "\n type" + index + ".store(backing, address + " + offset + ", defaults[" + index + "]);\n "; }).join(''); var argNames = ['$Address', 'Partial', 'defaults'].concat(_toConsumableArray(fields.map(function (_, index) { return "type" + index; }))); var args = [_symbols.$Address, Partial, defaults].concat(_toConsumableArray(fields.map(function (field) { return field.type; }))); var body = "\n \"use strict\";\n return function storeStruct (backing, address, input) {\n if (input == null) {\n " + setEmpty + "\n }\n else if (input instanceof Partial) {\n backing.copy(address, input[$Address], Partial.byteLength);\n }\n else {\n var tmp;\n " + setValues + "\n }\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Create the `.accepts()` method for a list of fields. */ function createAccepts(fields) { var argNames = ['$Address'].concat(_toConsumableArray(fields.map(function (_, index) { return "type" + index; }))); var args = [_symbols.$Address].concat(_toConsumableArray(fields.map(function (field) { return field.type; }))); var body = "\n \"use strict\";\n return function accepts (input) {\n if (input == null || typeof input !== 'object') {\n return false;\n }\n " + fields.map(function (_ref3, index) { var name = _ref3.name; var type = _ref3.type; var offset = _ref3.offset; return "\n if (!type" + index + ".accepts(input" + (isValidIdentifier(name) ? "." + name : "[" + JSON.stringify(name) + "]") + ")) {\n return false;\n }\n "; }).join('') + "\n return true;\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Create the `.toJSON()` method for a list of fields. */ function createToJSON(fields) { return Function("\n \"use strict\";\n return {\n " + fields.map(function (_ref4) { var name = _ref4.name; if (isValidIdentifier(name)) { return name + ": this." + name; } else { var sanitizedName = JSON.stringify(name); return sanitizedName + ": this[" + sanitizedName + "]"; } }).join(',\n ') + "\n };"); } /** * Create a function which can clear the given struct fields. */ function createClearStruct(fields) { var clearable = fields.filter(function (_ref5) { var type = _ref5.type; return typeof type.clear === 'function'; }); var clearers = clearable.map(function (field) { return field.type.clear; }); var names = clearable.map(function (_, index) { return "clear_" + index; }); var body = "\n \"use strict\";\n return function clearStruct (backing, address) {\n " + names.map(function (name, index) { return name + "(backing, address + " + clearable[index].offset + ");"; }).join('\n ') + "\n };\n "; return Function.apply(undefined, _toConsumableArray(names).concat([body])).apply(undefined, _toConsumableArray(clearers)); } /** * Create a function which can destroy the given struct fields. */ function createStructDestructor(fields) { var clearable = fields.filter(function (_ref6) { var type = _ref6.type; /* Issue 252 */ return type[_symbols.$CanContainReferences] && typeof type.clear === 'function'; }); var clearers = clearable.map(function (field) { return field.type; }); var names = clearable.map(function (_, index) { return "clearable_" + index; }); var body = "\n \"use strict\";\n return function destructor (backing, address) {\n " + names.map(function (name, index) { return name + ".clear(backing, address + " + clearable[index].offset + ");"; }).join('\n ') + "\n };\n "; return Function.apply(undefined, _toConsumableArray(names).concat([body])).apply(undefined, _toConsumableArray(clearers)); } /** * Create a function which can compare two structs by address. */ function createCompareAddresses(fields) { var checkAddresses = fields.map(function (_ref7, index) { var offset = _ref7.offset; return "\n else if ((tmp = type" + index + ".compareAddresses(backing, a + " + offset + ", b + " + offset + ")) !== 0) {\n return tmp;\n }\n "; }).join(''); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref8) { var type = _ref8.type; return type; }); var body = "\n \"use strict\";\n return function compareAddresses (backing, a, b) {\n var tmp;\n\n if (a === b) {\n return 0;\n }\n else if (a === 0) {\n return -1;\n }\n else if (b === 0) {\n return 1;\n }\n " + checkAddresses + "\n else {\n return 0;\n }\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Create a function which can determine whether two structs are structurally equal. */ function createEqual(fields) { var checkValues = fields.map(function (_ref9, index) { var name = _ref9.name; var type = _ref9.type; if (typeof type.equal !== 'function') { throw new Error("Type " + type.name + " does not have an equal() method."); } if (isValidIdentifier(name)) { return "\n else if (!type" + index + ".equal(a." + name + ", b." + name + ")) {\n return false;\n }\n "; } else { var sanitizedName = JSON.stringify(name); return "\n else if (!type" + index + ".equal(a[" + sanitizedName + "], b[" + sanitizedName + "])) {\n return false;\n }\n "; } }).join(''); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref10) { var type = _ref10.type; return type; }); var body = "\n \"use strict\";\n return function equal (a, b) {\n if (a === b) {\n return true;\n }\n else if (a == null || b == null) {\n return false;\n }\n " + checkValues + "\n else {\n return true;\n }\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Create a function which can compare two struct instances. */ function createCompareValues(fields) { var checkValues = fields.map(function (_ref11, index) { var name = _ref11.name; if (isValidIdentifier(name)) { return "\n else if ((tmp = type" + index + ".compareValues(a." + name + ", b." + name + ")) !== 0) {\n return tmp;\n }\n "; } else { var sanitizedName = JSON.stringify(name); return "\n else if ((tmp = type" + index + ".compareValues(a[" + sanitizedName + "], b[" + sanitizedName + "])) !== 0) {\n return tmp;\n }\n "; } }).join(''); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref12) { var type = _ref12.type; return type; }); var body = "\n \"use strict\";\n return function compareValues (a, b) {\n var tmp;\n if (a === b) {\n return 0;\n }\n else if (a == null) {\n return -1;\n }\n else if (b == null) {\n return 1;\n }\n " + checkValues + "\n else {\n return 0;\n }\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Create a function which can compare a struct stored at a given address with a given value. */ function createCompareAddressValue(fields) { var checkAddressValues = fields.map(function (_ref13, index) { var name = _ref13.name; var offset = _ref13.offset; if (isValidIdentifier(name)) { return "\n else if ((tmp = type" + index + ".compareAddressValue(backing, address + " + offset + ", value." + name + ")) !== 0) {\n return tmp;\n }\n "; } else { var sanitizedName = JSON.stringify(name); return "\n else if ((tmp = type" + index + ".compareAddressValue(backing, address, value[" + sanitizedName + "])) !== 0) {\n return tmp;\n }\n "; } }).join(''); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref14) { var type = _ref14.type; return type; }); var body = "\n \"use strict\";\n return function compareAddressValue (backing, address, value) {\n var tmp;\n if (value == null || typeof value !== 'object') {\n return 1;\n }\n else if (value[$Address] === address) {\n return 0;\n }\n " + checkAddressValues + "\n else {\n return 0;\n }\n };\n "; return Function.apply(undefined, ['$Address'].concat(_toConsumableArray(argNames), [body])).apply(undefined, [_symbols.$Address].concat(_toConsumableArray(args))); } /** * Create a function which can hash structs with the given fields. */ function createHashStruct(fields) { var checkValues = fields.map(function (_ref15, index) { var name = _ref15.name; var type = _ref15.type; if (typeof type.hashValue !== 'function') { throw new Error("Type " + type.name + " does not have a method called \"hashValue\"."); } if (isValidIdentifier(name)) { return "\n hash ^= type" + index + ".hashValue(input." + name + ");\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n "; } else { var sanitizedName = JSON.stringify(name); return "\n hash ^= type" + index + ".hashValue(input[" + sanitizedName + "]);\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n "; } }).join(''); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref16) { var type = _ref16.type; return type; }); var body = "\n \"use strict\";\n return function hashStruct (input) {\n var hash = 0x811c9dc5;\n\n " + checkValues + "\n\n return hash >>> 0;\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } /** * Creates a function which can return random objects with the same shape as the struct. */ function createRandomValue(fields) { var properties = fields.map(function (_ref17, index) { var name = _ref17.name; if (isValidIdentifier(name)) { return " " + name + ": type" + index + ".randomValue()"; } else { var sanitizedName = JSON.stringify(name); return " " + sanitizedName + ": type" + index + ".randomValue()"; } }).join(',\n'); var argNames = fields.map(function (_, index) { return "type" + index; }); var args = fields.map(function (_ref18) { var type = _ref18.type; return type; }); var body = "\n \"use strict\";\n return function randomValue () {\n return new this({\n " + properties + "\n });\n };\n "; return Function.apply(undefined, _toConsumableArray(argNames).concat([body])).apply(undefined, _toConsumableArray(args)); } function isValidIdentifier(name) { return (/^([A-Za-z_$])([A-Za-z_$0-9]*)$/.test(name) ); }