reign
Version:
A persistent, typed-objects implementation.
231 lines (196 loc) • 6.17 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 }; }
const MIN_TYPE_ID = exports.MIN_TYPE_ID = Math.pow(2, 20) * 9;function make(realm) {
const TypeClass = realm.TypeClass;
let typeCounter = 0;
function createTinyEnumType(Enum, possibleValues) {
const name = possibleValues.map(value => (0, _util.inspect)(value)).join(' | ');
const id = MIN_TYPE_ID + typeCounter;
const byteAlignment = 1;
const byteLength = 1;
function enumAccepts(input) {
const length = possibleValues.length;
for (let i = 0; i < length; i++) {
if (input === possibleValues[i]) {
return true;
}
}
return false;
}
function indexFor(value) {
const length = possibleValues.length;
for (let i = 0; i < length; i++) {
if (value === possibleValues[i]) {
return i;
}
}
return -1;
}
function initializeEnum(backing, address, initialValue) {
let 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) {
const 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) {
const name = possibleValues.map(value => (0, _util.inspect)(value)).join(' | ');
const id = MIN_TYPE_ID + typeCounter;
const byteAlignment = 2;
const byteLength = 2;
const valueMap = new Map(possibleValues.map((value, index) => [value, index]));
function enumAccepts(input) {
return valueMap.has(input);
}
function indexFor(value) {
const index = valueMap.get(value);
if (typeof index === 'number') {
return index;
} else {
return -1;
}
}
function initializeEnum(backing, address, initialValue) {
let 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) {
const 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 Enum => {
typeCounter++;
let EnumArray;
// 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);
}
};
});
};