Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / protobufjs / src / enum.js
1 "use strict";
2 module.exports = Enum;
3
4 // extends ReflectionObject
5 var ReflectionObject = require("./object");
6 ((Enum.prototype = Object.create(ReflectionObject.prototype)).constructor = Enum).className = "Enum";
7
8 var Namespace = require("./namespace"),
9     util = require("./util");
10
11 /**
12  * Constructs a new enum instance.
13  * @classdesc Reflected enum.
14  * @extends ReflectionObject
15  * @constructor
16  * @param {string} name Unique name within its namespace
17  * @param {Object.<string,number>} [values] Enum values as an object, by name
18  * @param {Object.<string,*>} [options] Declared options
19  * @param {string} [comment] The comment for this enum
20  * @param {Object.<string,string>} [comments] The value comments for this enum
21  */
22 function Enum(name, values, options, comment, comments) {
23     ReflectionObject.call(this, name, options);
24
25     if (values && typeof values !== "object")
26         throw TypeError("values must be an object");
27
28     /**
29      * Enum values by id.
30      * @type {Object.<number,string>}
31      */
32     this.valuesById = {};
33
34     /**
35      * Enum values by name.
36      * @type {Object.<string,number>}
37      */
38     this.values = Object.create(this.valuesById); // toJSON, marker
39
40     /**
41      * Enum comment text.
42      * @type {string|null}
43      */
44     this.comment = comment;
45
46     /**
47      * Value comment texts, if any.
48      * @type {Object.<string,string>}
49      */
50     this.comments = comments || {};
51
52     /**
53      * Reserved ranges, if any.
54      * @type {Array.<number[]|string>}
55      */
56     this.reserved = undefined; // toJSON
57
58     // Note that values inherit valuesById on their prototype which makes them a TypeScript-
59     // compatible enum. This is used by pbts to write actual enum definitions that work for
60     // static and reflection code alike instead of emitting generic object definitions.
61
62     if (values)
63         for (var keys = Object.keys(values), i = 0; i < keys.length; ++i)
64             if (typeof values[keys[i]] === "number") // use forward entries only
65                 this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
66 }
67
68 /**
69  * Enum descriptor.
70  * @interface IEnum
71  * @property {Object.<string,number>} values Enum values
72  * @property {Object.<string,*>} [options] Enum options
73  */
74
75 /**
76  * Constructs an enum from an enum descriptor.
77  * @param {string} name Enum name
78  * @param {IEnum} json Enum descriptor
79  * @returns {Enum} Created enum
80  * @throws {TypeError} If arguments are invalid
81  */
82 Enum.fromJSON = function fromJSON(name, json) {
83     var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
84     enm.reserved = json.reserved;
85     return enm;
86 };
87
88 /**
89  * Converts this enum to an enum descriptor.
90  * @param {IToJSONOptions} [toJSONOptions] JSON conversion options
91  * @returns {IEnum} Enum descriptor
92  */
93 Enum.prototype.toJSON = function toJSON(toJSONOptions) {
94     var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
95     return util.toObject([
96         "options"  , this.options,
97         "values"   , this.values,
98         "reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
99         "comment"  , keepComments ? this.comment : undefined,
100         "comments" , keepComments ? this.comments : undefined
101     ]);
102 };
103
104 /**
105  * Adds a value to this enum.
106  * @param {string} name Value name
107  * @param {number} id Value id
108  * @param {string} [comment] Comment, if any
109  * @returns {Enum} `this`
110  * @throws {TypeError} If arguments are invalid
111  * @throws {Error} If there is already a value with this name or id
112  */
113 Enum.prototype.add = function add(name, id, comment) {
114     // utilized by the parser but not by .fromJSON
115
116     if (!util.isString(name))
117         throw TypeError("name must be a string");
118
119     if (!util.isInteger(id))
120         throw TypeError("id must be an integer");
121
122     if (this.values[name] !== undefined)
123         throw Error("duplicate name '" + name + "' in " + this);
124
125     if (this.isReservedId(id))
126         throw Error("id " + id + " is reserved in " + this);
127
128     if (this.isReservedName(name))
129         throw Error("name '" + name + "' is reserved in " + this);
130
131     if (this.valuesById[id] !== undefined) {
132         if (!(this.options && this.options.allow_alias))
133             throw Error("duplicate id " + id + " in " + this);
134         this.values[name] = id;
135     } else
136         this.valuesById[this.values[name] = id] = name;
137
138     this.comments[name] = comment || null;
139     return this;
140 };
141
142 /**
143  * Removes a value from this enum
144  * @param {string} name Value name
145  * @returns {Enum} `this`
146  * @throws {TypeError} If arguments are invalid
147  * @throws {Error} If `name` is not a name of this enum
148  */
149 Enum.prototype.remove = function remove(name) {
150
151     if (!util.isString(name))
152         throw TypeError("name must be a string");
153
154     var val = this.values[name];
155     if (val == null)
156         throw Error("name '" + name + "' does not exist in " + this);
157
158     delete this.valuesById[val];
159     delete this.values[name];
160     delete this.comments[name];
161
162     return this;
163 };
164
165 /**
166  * Tests if the specified id is reserved.
167  * @param {number} id Id to test
168  * @returns {boolean} `true` if reserved, otherwise `false`
169  */
170 Enum.prototype.isReservedId = function isReservedId(id) {
171     return Namespace.isReservedId(this.reserved, id);
172 };
173
174 /**
175  * Tests if the specified name is reserved.
176  * @param {string} name Name to test
177  * @returns {boolean} `true` if reserved, otherwise `false`
178  */
179 Enum.prototype.isReservedName = function isReservedName(name) {
180     return Namespace.isReservedName(this.reserved, name);
181 };