123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- "use strict";
- module.exports = Enum;
-
- // extends ReflectionObject
- var ReflectionObject = require("./object");
- ((Enum.prototype = Object.create(ReflectionObject.prototype)).constructor = Enum).className = "Enum";
-
- var Namespace = require("./namespace"),
- util = require("./util");
-
- /**
- * Constructs a new enum instance.
- * @classdesc Reflected enum.
- * @extends ReflectionObject
- * @constructor
- * @param {string} name Unique name within its namespace
- * @param {Object.<string,number>} [values] Enum values as an object, by name
- * @param {Object.<string,*>} [options] Declared options
- * @param {string} [comment] The comment for this enum
- * @param {Object.<string,string>} [comments] The value comments for this enum
- */
- function Enum(name, values, options, comment, comments) {
- ReflectionObject.call(this, name, options);
-
- if (values && typeof values !== "object")
- throw TypeError("values must be an object");
-
- /**
- * Enum values by id.
- * @type {Object.<number,string>}
- */
- this.valuesById = {};
-
- /**
- * Enum values by name.
- * @type {Object.<string,number>}
- */
- this.values = Object.create(this.valuesById); // toJSON, marker
-
- /**
- * Enum comment text.
- * @type {string|null}
- */
- this.comment = comment;
-
- /**
- * Value comment texts, if any.
- * @type {Object.<string,string>}
- */
- this.comments = comments || {};
-
- /**
- * Reserved ranges, if any.
- * @type {Array.<number[]|string>}
- */
- this.reserved = undefined; // toJSON
-
- // Note that values inherit valuesById on their prototype which makes them a TypeScript-
- // compatible enum. This is used by pbts to write actual enum definitions that work for
- // static and reflection code alike instead of emitting generic object definitions.
-
- if (values)
- for (var keys = Object.keys(values), i = 0; i < keys.length; ++i)
- if (typeof values[keys[i]] === "number") // use forward entries only
- this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
- }
-
- /**
- * Enum descriptor.
- * @interface IEnum
- * @property {Object.<string,number>} values Enum values
- * @property {Object.<string,*>} [options] Enum options
- */
-
- /**
- * Constructs an enum from an enum descriptor.
- * @param {string} name Enum name
- * @param {IEnum} json Enum descriptor
- * @returns {Enum} Created enum
- * @throws {TypeError} If arguments are invalid
- */
- Enum.fromJSON = function fromJSON(name, json) {
- var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
- enm.reserved = json.reserved;
- return enm;
- };
-
- /**
- * Converts this enum to an enum descriptor.
- * @param {IToJSONOptions} [toJSONOptions] JSON conversion options
- * @returns {IEnum} Enum descriptor
- */
- Enum.prototype.toJSON = function toJSON(toJSONOptions) {
- var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
- return util.toObject([
- "options" , this.options,
- "values" , this.values,
- "reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
- "comment" , keepComments ? this.comment : undefined,
- "comments" , keepComments ? this.comments : undefined
- ]);
- };
-
- /**
- * Adds a value to this enum.
- * @param {string} name Value name
- * @param {number} id Value id
- * @param {string} [comment] Comment, if any
- * @returns {Enum} `this`
- * @throws {TypeError} If arguments are invalid
- * @throws {Error} If there is already a value with this name or id
- */
- Enum.prototype.add = function add(name, id, comment) {
- // utilized by the parser but not by .fromJSON
-
- if (!util.isString(name))
- throw TypeError("name must be a string");
-
- if (!util.isInteger(id))
- throw TypeError("id must be an integer");
-
- if (this.values[name] !== undefined)
- throw Error("duplicate name '" + name + "' in " + this);
-
- if (this.isReservedId(id))
- throw Error("id " + id + " is reserved in " + this);
-
- if (this.isReservedName(name))
- throw Error("name '" + name + "' is reserved in " + this);
-
- if (this.valuesById[id] !== undefined) {
- if (!(this.options && this.options.allow_alias))
- throw Error("duplicate id " + id + " in " + this);
- this.values[name] = id;
- } else
- this.valuesById[this.values[name] = id] = name;
-
- this.comments[name] = comment || null;
- return this;
- };
-
- /**
- * Removes a value from this enum
- * @param {string} name Value name
- * @returns {Enum} `this`
- * @throws {TypeError} If arguments are invalid
- * @throws {Error} If `name` is not a name of this enum
- */
- Enum.prototype.remove = function remove(name) {
-
- if (!util.isString(name))
- throw TypeError("name must be a string");
-
- var val = this.values[name];
- if (val == null)
- throw Error("name '" + name + "' does not exist in " + this);
-
- delete this.valuesById[val];
- delete this.values[name];
- delete this.comments[name];
-
- return this;
- };
-
- /**
- * Tests if the specified id is reserved.
- * @param {number} id Id to test
- * @returns {boolean} `true` if reserved, otherwise `false`
- */
- Enum.prototype.isReservedId = function isReservedId(id) {
- return Namespace.isReservedId(this.reserved, id);
- };
-
- /**
- * Tests if the specified name is reserved.
- * @param {string} name Name to test
- * @returns {boolean} `true` if reserved, otherwise `false`
- */
- Enum.prototype.isReservedName = function isReservedName(name) {
- return Namespace.isReservedName(this.reserved, name);
- };
|