4 // used to return a Promise where callback is omitted
5 util.asPromise = require("@protobufjs/aspromise");
7 // converts to / from base64 encoded strings
8 util.base64 = require("@protobufjs/base64");
10 // base class of rpc.Service
11 util.EventEmitter = require("@protobufjs/eventemitter");
13 // float handling accross browsers
14 util.float = require("@protobufjs/float");
16 // requires modules optionally and hides the call from bundlers
17 util.inquire = require("@protobufjs/inquire");
19 // converts to / from utf8 encoded strings
20 util.utf8 = require("@protobufjs/utf8");
22 // provides a node-like buffer pool in the browser
23 util.pool = require("@protobufjs/pool");
25 // utility to work with the low and high bits of a 64 bit value
26 util.LongBits = require("./longbits");
29 * Whether running within node or not.
33 util.isNode = Boolean(typeof global !== "undefined"
36 && global.process.versions
37 && global.process.versions.node);
40 * Global object reference.
44 util.global = util.isNode && global
45 || typeof window !== "undefined" && window
46 || typeof self !== "undefined" && self
47 || this; // eslint-disable-line no-invalid-this
50 * An immuable empty array.
55 util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes
58 * An immutable empty object.
62 util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes
65 * Tests if the specified value is an integer.
67 * @param {*} value Value to test
68 * @returns {boolean} `true` if the value is an integer
70 util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) {
71 return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
75 * Tests if the specified value is a string.
76 * @param {*} value Value to test
77 * @returns {boolean} `true` if the value is a string
79 util.isString = function isString(value) {
80 return typeof value === "string" || value instanceof String;
84 * Tests if the specified value is a non-null object.
85 * @param {*} value Value to test
86 * @returns {boolean} `true` if the value is a non-null object
88 util.isObject = function isObject(value) {
89 return value && typeof value === "object";
93 * Checks if a property on a message is considered to be present.
94 * This is an alias of {@link util.isSet}.
96 * @param {Object} obj Plain object or message instance
97 * @param {string} prop Property name
98 * @returns {boolean} `true` if considered to be present, otherwise `false`
103 * Checks if a property on a message is considered to be present.
104 * @param {Object} obj Plain object or message instance
105 * @param {string} prop Property name
106 * @returns {boolean} `true` if considered to be present, otherwise `false`
108 util.isSet = function isSet(obj, prop) {
109 var value = obj[prop];
110 if (value != null && obj.hasOwnProperty(prop)) // eslint-disable-line eqeqeq, no-prototype-builtins
111 return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
116 * Any compatible Buffer instance.
117 * This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings.
119 * @extends Uint8Array
123 * Node's Buffer class if available.
124 * @type {Constructor<Buffer>}
126 util.Buffer = (function() {
128 var Buffer = util.inquire("buffer").Buffer;
129 // refuse to use non-node buffers if not explicitly assigned (perf reasons):
130 return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null;
132 /* istanbul ignore next */
137 // Internal alias of or polyfull for Buffer.from.
138 util._Buffer_from = null;
140 // Internal alias of or polyfill for Buffer.allocUnsafe.
141 util._Buffer_allocUnsafe = null;
144 * Creates a new buffer of whatever type supported by the environment.
145 * @param {number|number[]} [sizeOrArray=0] Buffer size or number array
146 * @returns {Uint8Array|Buffer} Buffer
148 util.newBuffer = function newBuffer(sizeOrArray) {
149 /* istanbul ignore next */
150 return typeof sizeOrArray === "number"
152 ? util._Buffer_allocUnsafe(sizeOrArray)
153 : new util.Array(sizeOrArray)
155 ? util._Buffer_from(sizeOrArray)
156 : typeof Uint8Array === "undefined"
158 : new Uint8Array(sizeOrArray);
162 * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`.
163 * @type {Constructor<Uint8Array>}
165 util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array;
168 * Any compatible Long instance.
169 * This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
171 * @property {number} low Low bits
172 * @property {number} high High bits
173 * @property {boolean} unsigned Whether unsigned or not
177 * Long.js's Long class if available.
178 * @type {Constructor<Long>}
180 util.Long = /* istanbul ignore next */ util.global.dcodeIO && /* istanbul ignore next */ util.global.dcodeIO.Long
181 || /* istanbul ignore next */ util.global.Long
182 || util.inquire("long");
185 * Regular expression used to verify 2 bit (`bool`) map keys.
189 util.key2Re = /^true|false|0|1$/;
192 * Regular expression used to verify 32 bit (`int32` etc.) map keys.
196 util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
199 * Regular expression used to verify 64 bit (`int64` etc.) map keys.
203 util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;
206 * Converts a number or long to an 8 characters long hash string.
207 * @param {Long|number} value Value to convert
208 * @returns {string} Hash
210 util.longToHash = function longToHash(value) {
212 ? util.LongBits.from(value).toHash()
213 : util.LongBits.zeroHash;
217 * Converts an 8 characters long hash string to a long or number.
218 * @param {string} hash Hash
219 * @param {boolean} [unsigned=false] Whether unsigned or not
220 * @returns {Long|number} Original value
222 util.longFromHash = function longFromHash(hash, unsigned) {
223 var bits = util.LongBits.fromHash(hash);
225 return util.Long.fromBits(bits.lo, bits.hi, unsigned);
226 return bits.toNumber(Boolean(unsigned));
230 * Merges the properties of the source object into the destination object.
232 * @param {Object.<string,*>} dst Destination object
233 * @param {Object.<string,*>} src Source object
234 * @param {boolean} [ifNotSet=false] Merges only if the key is not already set
235 * @returns {Object.<string,*>} Destination object
237 function merge(dst, src, ifNotSet) { // used by converters
238 for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
239 if (dst[keys[i]] === undefined || !ifNotSet)
240 dst[keys[i]] = src[keys[i]];
247 * Converts the first character of a string to lower case.
248 * @param {string} str String to convert
249 * @returns {string} Converted string
251 util.lcFirst = function lcFirst(str) {
252 return str.charAt(0).toLowerCase() + str.substring(1);
256 * Creates a custom error constructor.
258 * @param {string} name Error name
259 * @returns {Constructor<Error>} Custom error constructor
261 function newError(name) {
263 function CustomError(message, properties) {
265 if (!(this instanceof CustomError))
266 return new CustomError(message, properties);
268 // Error.call(this, message);
269 // ^ just returns a new error instance because the ctor can be called as a function
271 Object.defineProperty(this, "message", { get: function() { return message; } });
273 /* istanbul ignore next */
274 if (Error.captureStackTrace) // node
275 Error.captureStackTrace(this, CustomError);
277 Object.defineProperty(this, "stack", { value: new Error().stack || "" });
280 merge(this, properties);
283 (CustomError.prototype = Object.create(Error.prototype)).constructor = CustomError;
285 Object.defineProperty(CustomError.prototype, "name", { get: function() { return name; } });
287 CustomError.prototype.toString = function toString() {
288 return this.name + ": " + this.message;
294 util.newError = newError;
297 * Constructs a new protocol error.
298 * @classdesc Error subclass indicating a protocol specifc error.
301 * @template T extends Message<T>
303 * @param {string} message Error message
304 * @param {Object.<string,*>} [properties] Additional properties
307 * MyMessage.decode(someBuffer); // throws if required fields are missing
309 * if (e instanceof ProtocolError && e.instance)
310 * console.log("decoded so far: " + JSON.stringify(e.instance));
313 util.ProtocolError = newError("ProtocolError");
316 * So far decoded message instance.
317 * @name util.ProtocolError#instance
322 * A OneOf getter as returned by {@link util.oneOfGetter}.
323 * @typedef OneOfGetter
325 * @returns {string|undefined} Set field name, if any
329 * Builds a getter for a oneof's present field name.
330 * @param {string[]} fieldNames Field names
331 * @returns {OneOfGetter} Unbound getter
333 util.oneOfGetter = function getOneOf(fieldNames) {
335 for (var i = 0; i < fieldNames.length; ++i)
336 fieldMap[fieldNames[i]] = 1;
339 * @returns {string|undefined} Set field name, if any
343 return function() { // eslint-disable-line consistent-return
344 for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i)
345 if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null)
351 * A OneOf setter as returned by {@link util.oneOfSetter}.
352 * @typedef OneOfSetter
354 * @param {string|undefined} value Field name
355 * @returns {undefined}
359 * Builds a setter for a oneof's present field name.
360 * @param {string[]} fieldNames Field names
361 * @returns {OneOfSetter} Unbound setter
363 util.oneOfSetter = function setOneOf(fieldNames) {
366 * @param {string} name Field name
367 * @returns {undefined}
371 return function(name) {
372 for (var i = 0; i < fieldNames.length; ++i)
373 if (fieldNames[i] !== name)
374 delete this[fieldNames[i]];
379 * Default conversion options used for {@link Message#toJSON} implementations.
381 * These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely:
383 * - Longs become strings
384 * - Enums become string keys
385 * - Bytes become base64 encoded strings
386 * - (Sub-)Messages become plain objects
387 * - Maps become plain objects with all string keys
388 * - Repeated fields become arrays
389 * - NaN and Infinity for float and double fields become strings
391 * @type {IConversionOptions}
392 * @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json
394 util.toJSONOptions = {
401 // Sets up buffer utility according to the environment (called in index-minimal)
402 util._configure = function() {
403 var Buffer = util.Buffer;
404 /* istanbul ignore if */
406 util._Buffer_from = util._Buffer_allocUnsafe = null;
409 // because node 4.x buffers are incompatible & immutable
410 // see: https://github.com/dcodeIO/protobuf.js/pull/665
411 util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from ||
412 /* istanbul ignore next */
413 function Buffer_from(value, encoding) {
414 return new Buffer(value, encoding);
416 util._Buffer_allocUnsafe = Buffer.allocUnsafe ||
417 /* istanbul ignore next */
418 function Buffer_allocUnsafe(size) {
419 return new Buffer(size);