reign
Version:
A persistent, typed-objects implementation.
237 lines (202 loc) • 6.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MIN_TYPE_ID = undefined;
exports.
/**
* Makes a EnumType type class for the given realm.
*/
make = make;
var _backing = require("backing");
var _backing2 = _interopRequireDefault(_backing);
var _util = require("util");
var _ = require("../");
var _util2 = require("../../util");
var _2 = require("../../");
var _symbols = require("../../symbols");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var MIN_TYPE_ID = exports.MIN_TYPE_ID = Math.pow(2, 20) * 9;function make(realm) {
var TypeClass = realm.TypeClass;
var typeCounter = 0;
function createTinyEnumType(Enum, possibleValues) {
var name = possibleValues.map(function (value) {
return (0, _util.inspect)(value);
}).join(' | ');
var id = MIN_TYPE_ID + typeCounter;
var byteAlignment = 1;
var byteLength = 1;
function enumAccepts(input) {
var length = possibleValues.length;
for (var i = 0; i < length; i++) {
if (input === possibleValues[i]) {
return true;
}
}
return false;
}
function indexFor(value) {
var length = possibleValues.length;
for (var i = 0; i < length; i++) {
if (value === possibleValues[i]) {
return i;
}
}
return -1;
}
function initializeEnum(backing, address, initialValue) {
var index = indexFor(initialValue);
if (index === -1) {
if (initialValue === undefined) {
index = 0;
} else {
throw new TypeError("Enum does not contain the given value: " + (0, _util.inspect)(initialValue));
}
}
backing.setUint8(address, index);
}
function storeEnum(backing, address, value) {
var index = indexFor(value);
if (index === -1) {
throw new TypeError("Enum does not contain the given value: " + (0, _util.inspect)(value));
}
backing.setUint8(address, index);
}
function loadEnum(backing, address) {
return possibleValues[backing.getUint8(address)];
}
function clearEnum(backing, address) {
backing.setUint8(address, 0);
}
function enumDestructor(backing, address) {
// no-op
}
return {
id: id,
name: name,
byteLength: byteLength,
byteAlignment: byteAlignment,
accepts: enumAccepts,
initialize: initializeEnum,
store: storeEnum,
load: loadEnum,
clear: clearEnum,
destructor: enumDestructor,
equal: function equal(a, b) {
return a === b;
},
emptyValue: function emptyValue() {
return possibleValues[0];
},
randomValue: function randomValue() {
return possibleValues[Math.floor(Math.random() * possibleValues.length)];
},
hashValue: function hashValue(input) {
return indexFor(input) + 777;
}
};
}
function createLargeEnumType(Enum, possibleValues) {
var name = possibleValues.map(function (value) {
return (0, _util.inspect)(value);
}).join(' | ');
var id = MIN_TYPE_ID + typeCounter;
var byteAlignment = 2;
var byteLength = 2;
var valueMap = new Map(possibleValues.map(function (value, index) {
return [value, index];
}));
function enumAccepts(input) {
return valueMap.has(input);
}
function indexFor(value) {
var index = valueMap.get(value);
if (typeof index === 'number') {
return index;
} else {
return -1;
}
}
function initializeEnum(backing, address, initialValue) {
var index = indexFor(initialValue);
if (index === -1) {
if (initialValue === undefined) {
index = 0;
} else {
throw new TypeError("Enum does not contain the given value: " + (0, _util.inspect)(initialValue));
}
}
backing.setUint16(address, index);
}
function storeEnum(backing, address, value) {
var index = indexFor(value);
if (index === -1) {
throw new TypeError("Enum does not contain the given value: " + (0, _util.inspect)(value));
}
backing.setUint16(address, index);
}
function loadEnum(backing, address) {
return possibleValues[backing.getUint16(address)];
}
function clearEnum(backing, address) {
backing.setUint16(address, 0);
}
function enumDestructor(backing, address) {
// no-op
}
return {
id: id,
name: name,
byteLength: byteLength,
byteAlignment: byteAlignment,
accepts: enumAccepts,
initialize: initializeEnum,
store: storeEnum,
load: loadEnum,
clear: clearEnum,
destructor: enumDestructor,
equal: function equal(a, b) {
return a === b;
},
emptyValue: function emptyValue() {
return possibleValues[0];
},
randomValue: function randomValue() {
return possibleValues[Math.floor(Math.random() * possibleValues.length)];
},
hashValue: function hashValue(input) {
return indexFor(input) + 777;
}
};
}
return new TypeClass('EnumType', function () {
for (var _len = arguments.length, possibleValues = Array(_len), _key = 0; _key < _len; _key++) {
possibleValues[_key] = arguments[_key];
}
return function (Enum) {
typeCounter++;
var EnumArray = void 0;
// Issue 285
Object.defineProperties(Enum, {
Array: {
get: function get() {
if (EnumArray === undefined) {
EnumArray = new realm.ArrayType(Enum);
}
return EnumArray;
}
}
});
Enum[_symbols.$CanBeEmbedded] = true;
Enum[_symbols.$CanBeReferenced] = false;
Enum[_symbols.$CanContainReferences] = false;
if (possibleValues.length >= Math.pow(2, 16)) {
throw new RangeError("Enum can only store up to " + Math.pow(2, 16) + " values.");
} else if (possibleValues.length >= 256) {
return createLargeEnumType(Enum, possibleValues);
} else {
return createTinyEnumType(Enum, possibleValues);
}
};
});
};