/*? // --- Scope ------------------ // T : Reflect.Message instance */ var fields = T.getChildren(ProtoBuf.Reflect.Message.Field), oneofs = T.getChildren(ProtoBuf.Reflect.Message.OneOf); /** * Constructs a new runtime Message. * @name ProtoBuf.Builder.Message * @class Barebone of all runtime messages. * @param {!Object.|string} values Preset values * @param {...string} var_args * @constructor * @throws {Error} If the message cannot be created */ var Message = function(values, var_args) { ProtoBuf.Builder.Message.call(this); // Create virtual oneof properties for (var i=0, k=oneofs.length; i 0) { var value; // Set field values from a values object if (arguments.length === 1 && values !== null && typeof values === 'object' && /* not _another_ Message */ (typeof values.encode !== 'function' || values instanceof Message) && /* not a repeated field */ !Array.isArray(values) && /* not a Map */ !(values instanceof ProtoBuf.Map) && /* not a ByteBuffer */ !ByteBuffer.isByteBuffer(values) && /* not an ArrayBuffer */ !(values instanceof ArrayBuffer) && /* not a Long */ !(ProtoBuf.Long && values instanceof ProtoBuf.Long)) { this.$set(values); } else // Set field values from arguments, in declaration order for (i=0, k=arguments.length; i} keyOrObj String key or plain object holding multiple values * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted * @param {boolean=} noAssert Whether to not assert for an actual field / proper value type, defaults to `false` * @returns {!ProtoBuf.Builder.Message} this * @throws {Error} If the value cannot be set * @expose */ MessagePrototype.set = function(keyOrObj, value, noAssert) { if (keyOrObj && typeof keyOrObj === 'object') { noAssert = value; for (var ikey in keyOrObj) { // Check if virtual oneof field - don't set these if (keyOrObj.hasOwnProperty(ikey) && typeof (value = keyOrObj[ikey]) !== 'undefined' && T._oneofsByName[ikey] === undefined) this.$set(ikey, value, noAssert); } return this; } var field = T._fieldsByName[keyOrObj]; if (!noAssert) { if (!field) throw Error(this+"#"+keyOrObj+" is not a field: undefined"); if (!(field instanceof ProtoBuf.Reflect.Message.Field)) throw Error(this+"#"+keyOrObj+" is not a field: "+field.toString(true)); this[field.name] = (value = field.verifyValue(value)); // May throw } else this[keyOrObj] = value; if (field && field.oneof) { // Field is part of an OneOf (not a virtual OneOf field) var currentField = this[field.oneof.name]; // Virtual field references currently set field if (value !== null) { if (currentField !== null && currentField !== field.name) this[currentField] = null; // Clear currently set field this[field.oneof.name] = field.name; // Point virtual field at this field } else if (/* value === null && */currentField === keyOrObj) this[field.oneof.name] = null; // Clear virtual field (current field explicitly cleared) } return this; }; /** * Sets a field's value. This is an alias for [@link ProtoBuf.Builder.Message#set}. * @name ProtoBuf.Builder.Message#$set * @function * @param {string|!Object.} keyOrObj String key or plain object holding multiple values * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted * @param {boolean=} noAssert Whether to not assert the value, defaults to `false` * @throws {Error} If the value cannot be set * @expose */ MessagePrototype.$set = MessagePrototype.set; /** * Gets a field's value. * @name ProtoBuf.Builder.Message#get * @function * @param {string} key Key * @param {boolean=} noAssert Whether to not assert for an actual field, defaults to `false` * @return {*} Value * @throws {Error} If there is no such field * @expose */ MessagePrototype.get = function(key, noAssert) { if (noAssert) return this[key]; var field = T._fieldsByName[key]; if (!field || !(field instanceof ProtoBuf.Reflect.Message.Field)) throw Error(this+"#"+key+" is not a field: undefined"); if (!(field instanceof ProtoBuf.Reflect.Message.Field)) throw Error(this+"#"+key+" is not a field: "+field.toString(true)); return this[field.name]; }; /** * Gets a field's value. This is an alias for {@link ProtoBuf.Builder.Message#$get}. * @name ProtoBuf.Builder.Message#$get * @function * @param {string} key Key * @return {*} Value * @throws {Error} If there is no such field * @expose */ MessagePrototype.$get = MessagePrototype.get; // Getters and setters for (var i=0; i} data Data payload * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false` * @return {!ByteBuffer} Encoded message as a ByteBuffer * @expose */ Message.encode = function(data, buffer, noVerify) { return new Message(data).encode(buffer, noVerify); }; /** * Calculates the byte length of the message. * @name ProtoBuf.Builder.Message#calculate * @function * @returns {number} Byte length * @throws {Error} If the message cannot be calculated or if required fields are missing. * @expose */ MessagePrototype.calculate = function() { return T.calculate(this); }; /** * Encodes the varint32 length-delimited message. * @name ProtoBuf.Builder.Message#encodeDelimited * @function * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false` * @return {!ByteBuffer} Encoded message as a ByteBuffer * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded ByteBuffer in the `encoded` property on the error. * @expose */ MessagePrototype.encodeDelimited = function(buffer, noVerify) { var isNew = false; if (!buffer) buffer = new ByteBuffer(), isNew = true; var enc = new ByteBuffer().LE(); T.encode(this, enc, noVerify).flip(); buffer.writeVarint32(enc.remaining()); buffer.append(enc); return isNew ? buffer.flip() : buffer; }; /** * Directly encodes the message to an ArrayBuffer. * @name ProtoBuf.Builder.Message#encodeAB * @function * @return {ArrayBuffer} Encoded message as ArrayBuffer * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded ArrayBuffer in the `encoded` property on the error. * @expose */ MessagePrototype.encodeAB = function() { try { return this.encode().toArrayBuffer(); } catch (e) { if (e["encoded"]) e["encoded"] = e["encoded"].toArrayBuffer(); throw(e); } }; /** * Returns the message as an ArrayBuffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeAB}. * @name ProtoBuf.Builder.Message#toArrayBuffer * @function * @return {ArrayBuffer} Encoded message as ArrayBuffer * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded ArrayBuffer in the `encoded` property on the error. * @expose */ MessagePrototype.toArrayBuffer = MessagePrototype.encodeAB; /** * Directly encodes the message to a node Buffer. * @name ProtoBuf.Builder.Message#encodeNB * @function * @return {!Buffer} * @throws {Error} If the message cannot be encoded, not running under node.js or if required fields are * missing. The later still returns the encoded node Buffer in the `encoded` property on the error. * @expose */ MessagePrototype.encodeNB = function() { try { return this.encode().toBuffer(); } catch (e) { if (e["encoded"]) e["encoded"] = e["encoded"].toBuffer(); throw(e); } }; /** * Returns the message as a node Buffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeNB}. * @name ProtoBuf.Builder.Message#toBuffer * @function * @return {!Buffer} * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded node Buffer in the `encoded` property on the error. * @expose */ MessagePrototype.toBuffer = MessagePrototype.encodeNB; /** * Directly encodes the message to a base64 encoded string. * @name ProtoBuf.Builder.Message#encode64 * @function * @return {string} Base64 encoded string * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later * still returns the encoded base64 string in the `encoded` property on the error. * @expose */ MessagePrototype.encode64 = function() { try { return this.encode().toBase64(); } catch (e) { if (e["encoded"]) e["encoded"] = e["encoded"].toBase64(); throw(e); } }; /** * Returns the message as a base64 encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encode64}. * @name ProtoBuf.Builder.Message#toBase64 * @function * @return {string} Base64 encoded string * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded base64 string in the `encoded` property on the error. * @expose */ MessagePrototype.toBase64 = MessagePrototype.encode64; /** * Directly encodes the message to a hex encoded string. * @name ProtoBuf.Builder.Message#encodeHex * @function * @return {string} Hex encoded string * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later * still returns the encoded hex string in the `encoded` property on the error. * @expose */ MessagePrototype.encodeHex = function() { try { return this.encode().toHex(); } catch (e) { if (e["encoded"]) e["encoded"] = e["encoded"].toHex(); throw(e); } }; /** * Returns the message as a hex encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encodeHex}. * @name ProtoBuf.Builder.Message#toHex * @function * @return {string} Hex encoded string * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still * returns the encoded hex string in the `encoded` property on the error. * @expose */ MessagePrototype.toHex = MessagePrototype.encodeHex; /** * Clones a message object or field value to a raw object. * @param {*} obj Object to clone * @param {boolean} binaryAsBase64 Whether to include binary data as base64 strings or as a buffer otherwise * @param {boolean} longsAsStrings Whether to encode longs as strings * @param {!ProtoBuf.Reflect.T=} resolvedType The resolved field type if a field * @returns {*} Cloned object * @inner */ function cloneRaw(obj, binaryAsBase64, longsAsStrings, resolvedType) { if (obj === null || typeof obj !== 'object') { // Convert enum values to their respective names if (resolvedType && resolvedType instanceof ProtoBuf.Reflect.Enum) { var name = ProtoBuf.Reflect.Enum.getName(resolvedType.object, obj); if (name !== null) return name; } // Pass-through string, number, boolean, null... return obj; } // Convert ByteBuffers to raw buffer or strings if (ByteBuffer.isByteBuffer(obj)) return binaryAsBase64 ? obj.toBase64() : obj.toBuffer(); // Convert Longs to proper objects or strings if (ProtoBuf.Long.isLong(obj)) return longsAsStrings ? obj.toString() : ProtoBuf.Long.fromValue(obj); var clone; // Clone arrays if (Array.isArray(obj)) { clone = []; obj.forEach(function(v, k) { clone[k] = cloneRaw(v, binaryAsBase64, longsAsStrings, resolvedType); }); return clone; } clone = {}; // Convert maps to objects if (obj instanceof ProtoBuf.Map) { var it = obj.entries(); for (var e = it.next(); !e.done; e = it.next()) clone[obj.keyElem.valueToString(e.value[0])] = cloneRaw(e.value[1], binaryAsBase64, longsAsStrings, obj.valueElem.resolvedType); return clone; } // Everything else is a non-null object var type = obj.$type, field = undefined; for (var i in obj) if (obj.hasOwnProperty(i)) { if (type && (field = type.getChild(i))) clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings, field.resolvedType); else clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings); } return clone; } /** * Returns the message's raw payload. * @param {boolean=} binaryAsBase64 Whether to include binary data as base64 strings instead of Buffers, defaults to `false` * @param {boolean} longsAsStrings Whether to encode longs as strings * @returns {Object.} Raw payload * @expose */ MessagePrototype.toRaw = function(binaryAsBase64, longsAsStrings) { return cloneRaw(this, !!binaryAsBase64, !!longsAsStrings, this.$type); }; /** * Encodes a message to JSON. * @returns {string} JSON string * @expose */ MessagePrototype.encodeJSON = function() { return JSON.stringify( cloneRaw(this, /* binary-as-base64 */ true, /* longs-as-strings */ true, this.$type ) ); }; /** * Decodes a message from the specified buffer or string. * @name ProtoBuf.Builder.Message.decode * @function * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from * @param {(number|string)=} length Message length. Defaults to decode all the remainig data. * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64 * @return {!ProtoBuf.Builder.Message} Decoded message * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still * returns the decoded message with missing fields in the `decoded` property on the error. * @expose * @see ProtoBuf.Builder.Message.decode64 * @see ProtoBuf.Builder.Message.decodeHex */ Message.decode = function(buffer, length, enc) { if (typeof length === 'string') enc = length, length = -1; if (typeof buffer === 'string') buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64"); else if (!ByteBuffer.isByteBuffer(buffer)) buffer = ByteBuffer.wrap(buffer); // May throw var le = buffer.littleEndian; try { var msg = T.decode(buffer.LE(), length); buffer.LE(le); return msg; } catch (e) { buffer.LE(le); throw(e); } }; /** * Decodes a varint32 length-delimited message from the specified buffer or string. * @name ProtoBuf.Builder.Message.decodeDelimited * @function * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64 * @return {ProtoBuf.Builder.Message} Decoded message or `null` if not enough bytes are available yet * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still * returns the decoded message with missing fields in the `decoded` property on the error. * @expose */ Message.decodeDelimited = function(buffer, enc) { if (typeof buffer === 'string') buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64"); else if (!ByteBuffer.isByteBuffer(buffer)) buffer = ByteBuffer.wrap(buffer); // May throw if (buffer.remaining() < 1) return null; var off = buffer.offset, len = buffer.readVarint32(); if (buffer.remaining() < len) { buffer.offset = off; return null; } try { var msg = T.decode(buffer.slice(buffer.offset, buffer.offset + len).LE()); buffer.offset += len; return msg; } catch (err) { buffer.offset += len; throw err; } }; /** * Decodes the message from the specified base64 encoded string. * @name ProtoBuf.Builder.Message.decode64 * @function * @param {string} str String to decode from * @return {!ProtoBuf.Builder.Message} Decoded message * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still * returns the decoded message with missing fields in the `decoded` property on the error. * @expose */ Message.decode64 = function(str) { return Message.decode(str, "base64"); }; /** * Decodes the message from the specified hex encoded string. * @name ProtoBuf.Builder.Message.decodeHex * @function * @param {string} str String to decode from * @return {!ProtoBuf.Builder.Message} Decoded message * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still * returns the decoded message with missing fields in the `decoded` property on the error. * @expose */ Message.decodeHex = function(str) { return Message.decode(str, "hex"); }; /** * Decodes the message from a JSON string. * @name ProtoBuf.Builder.Message.decodeJSON * @function * @param {string} str String to decode from * @return {!ProtoBuf.Builder.Message} Decoded message * @throws {Error} If the message cannot be decoded or if required fields are * missing. * @expose */ Message.decodeJSON = function(str) { return new Message(JSON.parse(str)); }; // Utility /** * Returns a string representation of this Message. * @name ProtoBuf.Builder.Message#toString * @function * @return {string} String representation as of ".Fully.Qualified.MessageName" * @expose */ MessagePrototype.toString = function() { return T.toString(); }; // Properties /** * Message options. * @name ProtoBuf.Builder.Message.$options * @type {Object.} * @expose */ var $optionsS; // cc needs this /** * Message options. * @name ProtoBuf.Builder.Message#$options * @type {Object.} * @expose */ var $options; /** * Reflection type. * @name ProtoBuf.Builder.Message.$type * @type {!ProtoBuf.Reflect.Message} * @expose */ var $typeS; /** * Reflection type. * @name ProtoBuf.Builder.Message#$type * @type {!ProtoBuf.Reflect.Message} * @expose */ var $type; if (Object.defineProperty) Object.defineProperty(Message, '$options', { "value": T.buildOpt() }), Object.defineProperty(MessagePrototype, "$options", { "value": Message["$options"] }), Object.defineProperty(Message, "$type", { "value": T }), Object.defineProperty(MessagePrototype, "$type", { "value": T });