UNPKG

reign

Version:

A persistent, typed-objects implementation.

231 lines (196 loc) 6.17 kB
"use strict"; 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); } }; }); };