; | |
var util = exports; | |
// used to return a Promise where callback is omitted | |
util.asPromise = require("@protobufjs/aspromise"); | |
// converts to / from base64 encoded strings | |
util.base64 = require("@protobufjs/base64"); | |
// base class of rpc.Service | |
util.EventEmitter = require("@protobufjs/eventemitter"); | |
// float handling accross browsers | |
util.float = require("@protobufjs/float"); | |
// requires modules optionally and hides the call from bundlers | |
util.inquire = require("@protobufjs/inquire"); | |
// converts to / from utf8 encoded strings | |
util.utf8 = require("@protobufjs/utf8"); | |
// provides a node-like buffer pool in the browser | |
util.pool = require("@protobufjs/pool"); | |
// utility to work with the low and high bits of a 64 bit value | |
util.LongBits = require("./longbits"); | |
/** | |
* Whether running within node or not. | |
* @memberof util | |
* @type {boolean} | |
*/ | |
util.isNode = Boolean(typeof global !== "undefined" | |
&& global | |
&& global.process | |
&& global.process.versions | |
&& global.process.versions.node); | |
/** | |
* Global object reference. | |
* @memberof util | |
* @type {Object} | |
*/ | |
util.global = util.isNode && global | |
|| typeof window !== "undefined" && window | |
|| typeof self !== "undefined" && self | |
|| this; // eslint-disable-line no-invalid-this | |
/** | |
* An immuable empty array. | |
* @memberof util | |
* @type {Array.<*>} | |
* @const | |
*/ | |
util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes | |
/** | |
* An immutable empty object. | |
* @type {Object} | |
* @const | |
*/ | |
util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes | |
/** | |
* Tests if the specified value is an integer. | |
* @function | |
* @param {*} value Value to test | |
* @returns {boolean} `true` if the value is an integer | |
*/ | |
util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) { | |
return typeof value === "number" && isFinite(value) && Math.floor(value) === value; | |
}; | |
/** | |
* Tests if the specified value is a string. | |
* @param {*} value Value to test | |
* @returns {boolean} `true` if the value is a string | |
*/ | |
util.isString = function isString(value) { | |
return typeof value === "string" || value instanceof String; | |
}; | |
/** | |
* Tests if the specified value is a non-null object. | |
* @param {*} value Value to test | |
* @returns {boolean} `true` if the value is a non-null object | |
*/ | |
util.isObject = function isObject(value) { | |
return value && typeof value === "object"; | |
}; | |
/** | |
* Checks if a property on a message is considered to be present. | |
* This is an alias of {@link util.isSet}. | |
* @function | |
* @param {Object} obj Plain object or message instance | |
* @param {string} prop Property name | |
* @returns {boolean} `true` if considered to be present, otherwise `false` | |
*/ | |
util.isset = | |
/** | |
* Checks if a property on a message is considered to be present. | |
* @param {Object} obj Plain object or message instance | |
* @param {string} prop Property name | |
* @returns {boolean} `true` if considered to be present, otherwise `false` | |
*/ | |
util.isSet = function isSet(obj, prop) { | |
var value = obj[prop]; | |
if (value != null && obj.hasOwnProperty(prop)) // eslint-disable-line eqeqeq, no-prototype-builtins | |
return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0; | |
return false; | |
}; | |
/** | |
* Any compatible Buffer instance. | |
* This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings. | |
* @interface Buffer | |
* @extends Uint8Array | |
*/ | |
/** | |
* Node's Buffer class if available. | |
* @type {Constructor<Buffer>} | |
*/ | |
util.Buffer = (function() { | |
try { | |
var Buffer = util.inquire("buffer").Buffer; | |
// refuse to use non-node buffers if not explicitly assigned (perf reasons): | |
return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null; | |
} catch (e) { | |
/* istanbul ignore next */ | |
return null; | |
} | |
})(); | |
// Internal alias of or polyfull for Buffer.from. | |
util._Buffer_from = null; | |
// Internal alias of or polyfill for Buffer.allocUnsafe. | |
util._Buffer_allocUnsafe = null; | |
/** | |
* Creates a new buffer of whatever type supported by the environment. | |
* @param {number|number[]} [sizeOrArray=0] Buffer size or number array | |
* @returns {Uint8Array|Buffer} Buffer | |
*/ | |
util.newBuffer = function newBuffer(sizeOrArray) { | |
/* istanbul ignore next */ | |
return typeof sizeOrArray === "number" | |
? util.Buffer | |
? util._Buffer_allocUnsafe(sizeOrArray) | |
: new util.Array(sizeOrArray) | |
: util.Buffer | |
? util._Buffer_from(sizeOrArray) | |
: typeof Uint8Array === "undefined" | |
? sizeOrArray | |
: new Uint8Array(sizeOrArray); | |
}; | |
/** | |
* Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`. | |
* @type {Constructor<Uint8Array>} | |
*/ | |
util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array; | |
/** | |
* Any compatible Long instance. | |
* This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js. | |
* @interface Long | |
* @property {number} low Low bits | |
* @property {number} high High bits | |
* @property {boolean} unsigned Whether unsigned or not | |
*/ | |
/** | |
* Long.js's Long class if available. | |
* @type {Constructor<Long>} | |
*/ | |
util.Long = /* istanbul ignore next */ util.global.dcodeIO && /* istanbul ignore next */ util.global.dcodeIO.Long | |
|| /* istanbul ignore next */ util.global.Long | |
|| util.inquire("long"); | |
/** | |
* Regular expression used to verify 2 bit (`bool`) map keys. | |
* @type {RegExp} | |
* @const | |
*/ | |
util.key2Re = /^true|false|0|1$/; | |
/** | |
* Regular expression used to verify 32 bit (`int32` etc.) map keys. | |
* @type {RegExp} | |
* @const | |
*/ | |
util.key32Re = /^-?(?:0|[1-9][0-9]*)$/; | |
/** | |
* Regular expression used to verify 64 bit (`int64` etc.) map keys. | |
* @type {RegExp} | |
* @const | |
*/ | |
util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/; | |
/** | |
* Converts a number or long to an 8 characters long hash string. | |
* @param {Long|number} value Value to convert | |
* @returns {string} Hash | |
*/ | |
util.longToHash = function longToHash(value) { | |
return value | |
? util.LongBits.from(value).toHash() | |
: util.LongBits.zeroHash; | |
}; | |
/** | |
* Converts an 8 characters long hash string to a long or number. | |
* @param {string} hash Hash | |
* @param {boolean} [unsigned=false] Whether unsigned or not | |
* @returns {Long|number} Original value | |
*/ | |
util.longFromHash = function longFromHash(hash, unsigned) { | |
var bits = util.LongBits.fromHash(hash); | |
if (util.Long) | |
return util.Long.fromBits(bits.lo, bits.hi, unsigned); | |
return bits.toNumber(Boolean(unsigned)); | |
}; | |
/** | |
* Merges the properties of the source object into the destination object. | |
* @memberof util | |
* @param {Object.<string,*>} dst Destination object | |
* @param {Object.<string,*>} src Source object | |
* @param {boolean} [ifNotSet=false] Merges only if the key is not already set | |
* @returns {Object.<string,*>} Destination object | |
*/ | |
function merge(dst, src, ifNotSet) { // used by converters | |
for (var keys = Object.keys(src), i = 0; i < keys.length; ++i) | |
if (dst[keys[i]] === undefined || !ifNotSet) | |
dst[keys[i]] = src[keys[i]]; | |
return dst; | |
} | |
util.merge = merge; | |
/** | |
* Converts the first character of a string to lower case. | |
* @param {string} str String to convert | |
* @returns {string} Converted string | |
*/ | |
util.lcFirst = function lcFirst(str) { | |
return str.charAt(0).toLowerCase() + str.substring(1); | |
}; | |
/** | |
* Creates a custom error constructor. | |
* @memberof util | |
* @param {string} name Error name | |
* @returns {Constructor<Error>} Custom error constructor | |
*/ | |
function newError(name) { | |
function CustomError(message, properties) { | |
if (!(this instanceof CustomError)) | |
return new CustomError(message, properties); | |
// Error.call(this, message); | |
// ^ just returns a new error instance because the ctor can be called as a function | |
Object.defineProperty(this, "message", { get: function() { return message; } }); | |
/* istanbul ignore next */ | |
if (Error.captureStackTrace) // node | |
Error.captureStackTrace(this, CustomError); | |
else | |
Object.defineProperty(this, "stack", { value: new Error().stack || "" }); | |
if (properties) | |
merge(this, properties); | |
} | |
CustomError.prototype = Object.create(Error.prototype, { | |
constructor: { | |
value: CustomError, | |
writable: true, | |
enumerable: false, | |
configurable: true, | |
}, | |
name: { | |
get: function get() { return name; }, | |
set: undefined, | |
enumerable: false, | |
// configurable: false would accurately preserve the behavior of | |
// the original, but I'm guessing that was not intentional. | |
// For an actual error subclass, this property would | |
// be configurable. | |
configurable: true, | |
}, | |
toString: { | |
value: function value() { return this.name + ": " + this.message; }, | |
writable: true, | |
enumerable: false, | |
configurable: true, | |
}, | |
}); | |
return CustomError; | |
} | |
util.newError = newError; | |
/** | |
* Constructs a new protocol error. | |
* @classdesc Error subclass indicating a protocol specifc error. | |
* @memberof util | |
* @extends Error | |
* @template T extends Message<T> | |
* @constructor | |
* @param {string} message Error message | |
* @param {Object.<string,*>} [properties] Additional properties | |
* @example | |
* try { | |
* MyMessage.decode(someBuffer); // throws if required fields are missing | |
* } catch (e) { | |
* if (e instanceof ProtocolError && e.instance) | |
* console.log("decoded so far: " + JSON.stringify(e.instance)); | |
* } | |
*/ | |
util.ProtocolError = newError("ProtocolError"); | |
/** | |
* So far decoded message instance. | |
* @name util.ProtocolError#instance | |
* @type {Message<T>} | |
*/ | |
/** | |
* A OneOf getter as returned by {@link util.oneOfGetter}. | |
* @typedef OneOfGetter | |
* @type {function} | |
* @returns {string|undefined} Set field name, if any | |
*/ | |
/** | |
* Builds a getter for a oneof's present field name. | |
* @param {string[]} fieldNames Field names | |
* @returns {OneOfGetter} Unbound getter | |
*/ | |
util.oneOfGetter = function getOneOf(fieldNames) { | |
var fieldMap = {}; | |
for (var i = 0; i < fieldNames.length; ++i) | |
fieldMap[fieldNames[i]] = 1; | |
/** | |
* @returns {string|undefined} Set field name, if any | |
* @this Object | |
* @ignore | |
*/ | |
return function() { // eslint-disable-line consistent-return | |
for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i) | |
if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null) | |
return keys[i]; | |
}; | |
}; | |
/** | |
* A OneOf setter as returned by {@link util.oneOfSetter}. | |
* @typedef OneOfSetter | |
* @type {function} | |
* @param {string|undefined} value Field name | |
* @returns {undefined} | |
*/ | |
/** | |
* Builds a setter for a oneof's present field name. | |
* @param {string[]} fieldNames Field names | |
* @returns {OneOfSetter} Unbound setter | |
*/ | |
util.oneOfSetter = function setOneOf(fieldNames) { | |
/** | |
* @param {string} name Field name | |
* @returns {undefined} | |
* @this Object | |
* @ignore | |
*/ | |
return function(name) { | |
for (var i = 0; i < fieldNames.length; ++i) | |
if (fieldNames[i] !== name) | |
delete this[fieldNames[i]]; | |
}; | |
}; | |
/** | |
* Default conversion options used for {@link Message#toJSON} implementations. | |
* | |
* These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely: | |
* | |
* - Longs become strings | |
* - Enums become string keys | |
* - Bytes become base64 encoded strings | |
* - (Sub-)Messages become plain objects | |
* - Maps become plain objects with all string keys | |
* - Repeated fields become arrays | |
* - NaN and Infinity for float and double fields become strings | |
* | |
* @type {IConversionOptions} | |
* @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json | |
*/ | |
util.toJSONOptions = { | |
longs: String, | |
enums: String, | |
bytes: String, | |
json: true | |
}; | |
// Sets up buffer utility according to the environment (called in index-minimal) | |
util._configure = function() { | |
var Buffer = util.Buffer; | |
/* istanbul ignore if */ | |
if (!Buffer) { | |
util._Buffer_from = util._Buffer_allocUnsafe = null; | |
return; | |
} | |
// because node 4.x buffers are incompatible & immutable | |
// see: https://github.com/dcodeIO/protobuf.js/pull/665 | |
util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from || | |
/* istanbul ignore next */ | |
function Buffer_from(value, encoding) { | |
return new Buffer(value, encoding); | |
}; | |
util._Buffer_allocUnsafe = Buffer.allocUnsafe || | |
/* istanbul ignore next */ | |
function Buffer_allocUnsafe(size) { | |
return new Buffer(size); | |
}; | |
}; | |