1ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 2ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 3ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 4ffe3c632Sopenharmony_ci// 5ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 6ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 7ffe3c632Sopenharmony_ci// met: 8ffe3c632Sopenharmony_ci// 9ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 10ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 11ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 12ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 13ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 14ffe3c632Sopenharmony_ci// distribution. 15ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 16ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 17ffe3c632Sopenharmony_ci// this software without specific prior written permission. 18ffe3c632Sopenharmony_ci// 19ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30ffe3c632Sopenharmony_ci 31ffe3c632Sopenharmony_ci/** 32ffe3c632Sopenharmony_ci * @fileoverview Definition of jspb.Message. 33ffe3c632Sopenharmony_ci * 34ffe3c632Sopenharmony_ci * @author mwr@google.com (Mark Rawling) 35ffe3c632Sopenharmony_ci */ 36ffe3c632Sopenharmony_ci 37ffe3c632Sopenharmony_cigoog.provide('jspb.ExtensionFieldBinaryInfo'); 38ffe3c632Sopenharmony_cigoog.provide('jspb.ExtensionFieldInfo'); 39ffe3c632Sopenharmony_cigoog.provide('jspb.Message'); 40ffe3c632Sopenharmony_ci 41ffe3c632Sopenharmony_cigoog.require('goog.array'); 42ffe3c632Sopenharmony_cigoog.require('goog.asserts'); 43ffe3c632Sopenharmony_cigoog.require('goog.crypt.base64'); 44ffe3c632Sopenharmony_cigoog.require('jspb.BinaryReader'); 45ffe3c632Sopenharmony_cigoog.require('jspb.Map'); 46ffe3c632Sopenharmony_ci 47ffe3c632Sopenharmony_ci 48ffe3c632Sopenharmony_ci 49ffe3c632Sopenharmony_ci 50ffe3c632Sopenharmony_ci/** 51ffe3c632Sopenharmony_ci * Stores information for a single extension field. 52ffe3c632Sopenharmony_ci * 53ffe3c632Sopenharmony_ci * For example, an extension field defined like so: 54ffe3c632Sopenharmony_ci * 55ffe3c632Sopenharmony_ci * extend BaseMessage { 56ffe3c632Sopenharmony_ci * optional MyMessage my_field = 123; 57ffe3c632Sopenharmony_ci * } 58ffe3c632Sopenharmony_ci * 59ffe3c632Sopenharmony_ci * will result in an ExtensionFieldInfo object with these properties: 60ffe3c632Sopenharmony_ci * 61ffe3c632Sopenharmony_ci * { 62ffe3c632Sopenharmony_ci * fieldIndex: 123, 63ffe3c632Sopenharmony_ci * fieldName: {my_field_renamed: 0}, 64ffe3c632Sopenharmony_ci * ctor: proto.example.MyMessage, 65ffe3c632Sopenharmony_ci * toObjectFn: proto.example.MyMessage.toObject, 66ffe3c632Sopenharmony_ci * isRepeated: 0 67ffe3c632Sopenharmony_ci * } 68ffe3c632Sopenharmony_ci * 69ffe3c632Sopenharmony_ci * We include `toObjectFn` to allow the JSCompiler to perform dead-code removal 70ffe3c632Sopenharmony_ci * on unused toObject() methods. 71ffe3c632Sopenharmony_ci * 72ffe3c632Sopenharmony_ci * If an extension field is primitive, ctor and toObjectFn will be null. 73ffe3c632Sopenharmony_ci * isRepeated should be 0 or 1. 74ffe3c632Sopenharmony_ci * 75ffe3c632Sopenharmony_ci * binary{Reader,Writer}Fn and (if message type) binaryMessageSerializeFn are 76ffe3c632Sopenharmony_ci * always provided. binaryReaderFn and binaryWriterFn are references to the 77ffe3c632Sopenharmony_ci * appropriate methods on BinaryReader/BinaryWriter to read/write the value of 78ffe3c632Sopenharmony_ci * this extension, and binaryMessageSerializeFn is a reference to the message 79ffe3c632Sopenharmony_ci * class's .serializeBinary method, if available. 80ffe3c632Sopenharmony_ci * 81ffe3c632Sopenharmony_ci * @param {number} fieldNumber 82ffe3c632Sopenharmony_ci * @param {Object} fieldName This has the extension field name as a property. 83ffe3c632Sopenharmony_ci * @param {?function(new: jspb.Message, Array=)} ctor 84ffe3c632Sopenharmony_ci * @param {?function((boolean|undefined),!jspb.Message):!Object} toObjectFn 85ffe3c632Sopenharmony_ci * @param {number} isRepeated 86ffe3c632Sopenharmony_ci * @constructor 87ffe3c632Sopenharmony_ci * @struct 88ffe3c632Sopenharmony_ci * @template T 89ffe3c632Sopenharmony_ci */ 90ffe3c632Sopenharmony_cijspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn, 91ffe3c632Sopenharmony_ci isRepeated) { 92ffe3c632Sopenharmony_ci /** @const */ 93ffe3c632Sopenharmony_ci this.fieldIndex = fieldNumber; 94ffe3c632Sopenharmony_ci /** @const */ 95ffe3c632Sopenharmony_ci this.fieldName = fieldName; 96ffe3c632Sopenharmony_ci /** @const */ 97ffe3c632Sopenharmony_ci this.ctor = ctor; 98ffe3c632Sopenharmony_ci /** @const */ 99ffe3c632Sopenharmony_ci this.toObjectFn = toObjectFn; 100ffe3c632Sopenharmony_ci /** @const */ 101ffe3c632Sopenharmony_ci this.isRepeated = isRepeated; 102ffe3c632Sopenharmony_ci}; 103ffe3c632Sopenharmony_ci 104ffe3c632Sopenharmony_ci/** 105ffe3c632Sopenharmony_ci * Stores binary-related information for a single extension field. 106ffe3c632Sopenharmony_ci * @param {!jspb.ExtensionFieldInfo<T>} fieldInfo 107ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryReader,number,?,?)} binaryReaderFn 108ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryWriter,number,?) 109ffe3c632Sopenharmony_ci * |function(this:jspb.BinaryWriter,number,?,?,?,?,?)} binaryWriterFn 110ffe3c632Sopenharmony_ci * @param {function(?,?)=} opt_binaryMessageSerializeFn 111ffe3c632Sopenharmony_ci * @param {function(?,?)=} opt_binaryMessageDeserializeFn 112ffe3c632Sopenharmony_ci * @param {boolean=} opt_isPacked 113ffe3c632Sopenharmony_ci * @constructor 114ffe3c632Sopenharmony_ci * @struct 115ffe3c632Sopenharmony_ci * @template T 116ffe3c632Sopenharmony_ci */ 117ffe3c632Sopenharmony_cijspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriterFn, 118ffe3c632Sopenharmony_ci opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn, opt_isPacked) { 119ffe3c632Sopenharmony_ci /** @const */ 120ffe3c632Sopenharmony_ci this.fieldInfo = fieldInfo; 121ffe3c632Sopenharmony_ci /** @const */ 122ffe3c632Sopenharmony_ci this.binaryReaderFn = binaryReaderFn; 123ffe3c632Sopenharmony_ci /** @const */ 124ffe3c632Sopenharmony_ci this.binaryWriterFn = binaryWriterFn; 125ffe3c632Sopenharmony_ci /** @const */ 126ffe3c632Sopenharmony_ci this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn; 127ffe3c632Sopenharmony_ci /** @const */ 128ffe3c632Sopenharmony_ci this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn; 129ffe3c632Sopenharmony_ci /** @const */ 130ffe3c632Sopenharmony_ci this.isPacked = opt_isPacked; 131ffe3c632Sopenharmony_ci}; 132ffe3c632Sopenharmony_ci 133ffe3c632Sopenharmony_ci/** 134ffe3c632Sopenharmony_ci * @return {boolean} Does this field represent a sub Message? 135ffe3c632Sopenharmony_ci */ 136ffe3c632Sopenharmony_cijspb.ExtensionFieldInfo.prototype.isMessageType = function() { 137ffe3c632Sopenharmony_ci return !!this.ctor; 138ffe3c632Sopenharmony_ci}; 139ffe3c632Sopenharmony_ci 140ffe3c632Sopenharmony_ci 141ffe3c632Sopenharmony_ci/** 142ffe3c632Sopenharmony_ci * Base class for all JsPb messages. 143ffe3c632Sopenharmony_ci * 144ffe3c632Sopenharmony_ci * Several common methods (toObject, serializeBinary, in particular) are not 145ffe3c632Sopenharmony_ci * defined on the prototype to encourage code patterns that minimize code bloat 146ffe3c632Sopenharmony_ci * due to otherwise unused code on all protos contained in the project. 147ffe3c632Sopenharmony_ci * 148ffe3c632Sopenharmony_ci * If you want to call these methods on a generic message, either 149ffe3c632Sopenharmony_ci * pass in your instance of method as a parameter: 150ffe3c632Sopenharmony_ci * someFunction(instanceOfKnownProto, 151ffe3c632Sopenharmony_ci * KnownProtoClass.prototype.serializeBinary); 152ffe3c632Sopenharmony_ci * or use a lambda that knows the type: 153ffe3c632Sopenharmony_ci * someFunction(()=>instanceOfKnownProto.serializeBinary()); 154ffe3c632Sopenharmony_ci * or, if you don't care about code size, just suppress the 155ffe3c632Sopenharmony_ci * WARNING - Property serializeBinary never defined on jspb.Message 156ffe3c632Sopenharmony_ci * and call it the intuitive way. 157ffe3c632Sopenharmony_ci * 158ffe3c632Sopenharmony_ci * @constructor 159ffe3c632Sopenharmony_ci * @struct 160ffe3c632Sopenharmony_ci */ 161ffe3c632Sopenharmony_cijspb.Message = function() { 162ffe3c632Sopenharmony_ci}; 163ffe3c632Sopenharmony_ci 164ffe3c632Sopenharmony_ci 165ffe3c632Sopenharmony_ci/** 166ffe3c632Sopenharmony_ci * @define {boolean} Whether to generate toObject methods for objects. Turn 167ffe3c632Sopenharmony_ci * this off, if you do not want toObject to be ever used in your project. 168ffe3c632Sopenharmony_ci * When turning off this flag, consider adding a conformance test that bans 169ffe3c632Sopenharmony_ci * calling toObject. Enabling this will disable the JSCompiler's ability to 170ffe3c632Sopenharmony_ci * dead code eliminate fields used in protocol buffers that are never used 171ffe3c632Sopenharmony_ci * in an application. 172ffe3c632Sopenharmony_ci */ 173ffe3c632Sopenharmony_cijspb.Message.GENERATE_TO_OBJECT = 174ffe3c632Sopenharmony_ci goog.define('jspb.Message.GENERATE_TO_OBJECT', true); 175ffe3c632Sopenharmony_ci 176ffe3c632Sopenharmony_ci 177ffe3c632Sopenharmony_ci/** 178ffe3c632Sopenharmony_ci * @define {boolean} Whether to generate fromObject methods for objects. Turn 179ffe3c632Sopenharmony_ci * this off, if you do not want fromObject to be ever used in your project. 180ffe3c632Sopenharmony_ci * When turning off this flag, consider adding a conformance test that bans 181ffe3c632Sopenharmony_ci * calling fromObject. Enabling this might disable the JSCompiler's ability 182ffe3c632Sopenharmony_ci * to dead code eliminate fields used in protocol buffers that are never 183ffe3c632Sopenharmony_ci * used in an application. 184ffe3c632Sopenharmony_ci * By default this is enabled for test code only. 185ffe3c632Sopenharmony_ci */ 186ffe3c632Sopenharmony_cijspb.Message.GENERATE_FROM_OBJECT = goog.define( 187ffe3c632Sopenharmony_ci 'jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE); 188ffe3c632Sopenharmony_ci 189ffe3c632Sopenharmony_ci 190ffe3c632Sopenharmony_ci/** 191ffe3c632Sopenharmony_ci * @define {boolean} Whether to generate toString methods for objects. Turn 192ffe3c632Sopenharmony_ci * this off if you do not use toString in your project and want to trim it 193ffe3c632Sopenharmony_ci * from the compiled JS. 194ffe3c632Sopenharmony_ci */ 195ffe3c632Sopenharmony_cijspb.Message.GENERATE_TO_STRING = 196ffe3c632Sopenharmony_ci goog.define('jspb.Message.GENERATE_TO_STRING', true); 197ffe3c632Sopenharmony_ci 198ffe3c632Sopenharmony_ci 199ffe3c632Sopenharmony_ci/** 200ffe3c632Sopenharmony_ci * @define {boolean} Whether arrays passed to initialize() can be assumed to be 201ffe3c632Sopenharmony_ci * local (e.g. not from another iframe) and thus safely classified with 202ffe3c632Sopenharmony_ci * instanceof Array. 203ffe3c632Sopenharmony_ci */ 204ffe3c632Sopenharmony_cijspb.Message.ASSUME_LOCAL_ARRAYS = 205ffe3c632Sopenharmony_ci goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false); 206ffe3c632Sopenharmony_ci 207ffe3c632Sopenharmony_ci 208ffe3c632Sopenharmony_ci// TODO(jakubvrana): Turn this off by default. 209ffe3c632Sopenharmony_ci/** 210ffe3c632Sopenharmony_ci * @define {boolean} Disabling the serialization of empty trailing fields 211ffe3c632Sopenharmony_ci * reduces the size of serialized protos. The price is an extra iteration of 212ffe3c632Sopenharmony_ci * the proto before serialization. This is enabled by default to be 213ffe3c632Sopenharmony_ci * backwards compatible. Projects are advised to turn this flag always off. 214ffe3c632Sopenharmony_ci */ 215ffe3c632Sopenharmony_cijspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS = 216ffe3c632Sopenharmony_ci goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true); 217ffe3c632Sopenharmony_ci 218ffe3c632Sopenharmony_ci 219ffe3c632Sopenharmony_ci/** 220ffe3c632Sopenharmony_ci * Does this JavaScript environment support Uint8Aray typed arrays? 221ffe3c632Sopenharmony_ci * @type {boolean} 222ffe3c632Sopenharmony_ci * @private 223ffe3c632Sopenharmony_ci */ 224ffe3c632Sopenharmony_cijspb.Message.SUPPORTS_UINT8ARRAY_ = (typeof Uint8Array == 'function'); 225ffe3c632Sopenharmony_ci 226ffe3c632Sopenharmony_ci 227ffe3c632Sopenharmony_ci/** 228ffe3c632Sopenharmony_ci * The internal data array. 229ffe3c632Sopenharmony_ci * @type {!Array} 230ffe3c632Sopenharmony_ci * @protected 231ffe3c632Sopenharmony_ci */ 232ffe3c632Sopenharmony_cijspb.Message.prototype.array; 233ffe3c632Sopenharmony_ci 234ffe3c632Sopenharmony_ci 235ffe3c632Sopenharmony_ci/** 236ffe3c632Sopenharmony_ci * Wrappers are the constructed instances of message-type fields. They are built 237ffe3c632Sopenharmony_ci * on demand from the raw array data. Includes message fields, repeated message 238ffe3c632Sopenharmony_ci * fields and extension message fields. Indexed by field number. 239ffe3c632Sopenharmony_ci * @type {Object} 240ffe3c632Sopenharmony_ci * @private 241ffe3c632Sopenharmony_ci */ 242ffe3c632Sopenharmony_cijspb.Message.prototype.wrappers_; 243ffe3c632Sopenharmony_ci 244ffe3c632Sopenharmony_ci 245ffe3c632Sopenharmony_ci/** 246ffe3c632Sopenharmony_ci * The object that contains extension fields, if any. This is an object that 247ffe3c632Sopenharmony_ci * maps from a proto field number to the field's value. 248ffe3c632Sopenharmony_ci * @type {Object} 249ffe3c632Sopenharmony_ci * @private 250ffe3c632Sopenharmony_ci */ 251ffe3c632Sopenharmony_cijspb.Message.prototype.extensionObject_; 252ffe3c632Sopenharmony_ci 253ffe3c632Sopenharmony_ci 254ffe3c632Sopenharmony_ci/** 255ffe3c632Sopenharmony_ci * Non-extension fields with a field number at or above the pivot are 256ffe3c632Sopenharmony_ci * stored in the extension object (in addition to all extension fields). 257ffe3c632Sopenharmony_ci * @type {number} 258ffe3c632Sopenharmony_ci * @private 259ffe3c632Sopenharmony_ci */ 260ffe3c632Sopenharmony_cijspb.Message.prototype.pivot_; 261ffe3c632Sopenharmony_ci 262ffe3c632Sopenharmony_ci 263ffe3c632Sopenharmony_ci/** 264ffe3c632Sopenharmony_ci * The JsPb message_id of this proto. 265ffe3c632Sopenharmony_ci * @type {string|undefined} the message id or undefined if this message 266ffe3c632Sopenharmony_ci * has no id. 267ffe3c632Sopenharmony_ci * @private 268ffe3c632Sopenharmony_ci */ 269ffe3c632Sopenharmony_cijspb.Message.prototype.messageId_; 270ffe3c632Sopenharmony_ci 271ffe3c632Sopenharmony_ci 272ffe3c632Sopenharmony_ci/** 273ffe3c632Sopenharmony_ci * Repeated fields that have been converted to their proper type. This is used 274ffe3c632Sopenharmony_ci * for numbers stored as strings (typically "NaN", "Infinity" and "-Infinity") 275ffe3c632Sopenharmony_ci * and for booleans stored as numbers (0 or 1). 276ffe3c632Sopenharmony_ci * @private {!Object<number,boolean>|undefined} 277ffe3c632Sopenharmony_ci */ 278ffe3c632Sopenharmony_cijspb.Message.prototype.convertedPrimitiveFields_; 279ffe3c632Sopenharmony_ci 280ffe3c632Sopenharmony_ci/** 281ffe3c632Sopenharmony_ci * Repeated fields numbers. 282ffe3c632Sopenharmony_ci * @protected {?Array<number>|undefined} 283ffe3c632Sopenharmony_ci */ 284ffe3c632Sopenharmony_cijspb.Message.prototype.repeatedFields; 285ffe3c632Sopenharmony_ci 286ffe3c632Sopenharmony_ci 287ffe3c632Sopenharmony_ci 288ffe3c632Sopenharmony_ci/** 289ffe3c632Sopenharmony_ci * Returns the JsPb message_id of this proto. 290ffe3c632Sopenharmony_ci * @return {string|undefined} the message id or undefined if this message 291ffe3c632Sopenharmony_ci * has no id. 292ffe3c632Sopenharmony_ci */ 293ffe3c632Sopenharmony_cijspb.Message.prototype.getJsPbMessageId = function() { 294ffe3c632Sopenharmony_ci return this.messageId_; 295ffe3c632Sopenharmony_ci}; 296ffe3c632Sopenharmony_ci 297ffe3c632Sopenharmony_ci 298ffe3c632Sopenharmony_ci/** 299ffe3c632Sopenharmony_ci * An offset applied to lookups into this.array to account for the presence or 300ffe3c632Sopenharmony_ci * absence of a messageId at position 0. For response messages, this will be 0. 301ffe3c632Sopenharmony_ci * Otherwise, it will be -1 so that the first array position is not wasted. 302ffe3c632Sopenharmony_ci * @type {number} 303ffe3c632Sopenharmony_ci * @private 304ffe3c632Sopenharmony_ci */ 305ffe3c632Sopenharmony_cijspb.Message.prototype.arrayIndexOffset_; 306ffe3c632Sopenharmony_ci 307ffe3c632Sopenharmony_ci 308ffe3c632Sopenharmony_ci/** 309ffe3c632Sopenharmony_ci * Returns the index into msg.array at which the proto field with tag number 310ffe3c632Sopenharmony_ci * fieldNumber will be located. 311ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg Message for which we're calculating an index. 312ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 313ffe3c632Sopenharmony_ci * @return {number} The index. 314ffe3c632Sopenharmony_ci * @private 315ffe3c632Sopenharmony_ci */ 316ffe3c632Sopenharmony_cijspb.Message.getIndex_ = function(msg, fieldNumber) { 317ffe3c632Sopenharmony_ci return fieldNumber + msg.arrayIndexOffset_; 318ffe3c632Sopenharmony_ci}; 319ffe3c632Sopenharmony_ci 320ffe3c632Sopenharmony_ci// This is only here to ensure we are not back sliding on ES6 requirements for 321ffe3c632Sopenharmony_ci// protos in g3. 322ffe3c632Sopenharmony_cijspb.Message.hiddenES6Property_ = class {}; 323ffe3c632Sopenharmony_ci 324ffe3c632Sopenharmony_ci 325ffe3c632Sopenharmony_ci/** 326ffe3c632Sopenharmony_ci * Returns the tag number based on the index in msg.array. 327ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg Message for which we're calculating an index. 328ffe3c632Sopenharmony_ci * @param {number} index The tag number. 329ffe3c632Sopenharmony_ci * @return {number} The field number. 330ffe3c632Sopenharmony_ci * @private 331ffe3c632Sopenharmony_ci */ 332ffe3c632Sopenharmony_cijspb.Message.getFieldNumber_ = function(msg, index) { 333ffe3c632Sopenharmony_ci return index - msg.arrayIndexOffset_; 334ffe3c632Sopenharmony_ci}; 335ffe3c632Sopenharmony_ci 336ffe3c632Sopenharmony_ci 337ffe3c632Sopenharmony_ci/** 338ffe3c632Sopenharmony_ci * Initializes a JsPb Message. 339ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg The JsPb proto to modify. 340ffe3c632Sopenharmony_ci * @param {Array|undefined} data An initial data array. 341ffe3c632Sopenharmony_ci * @param {string|number} messageId For response messages, the message id or '' 342ffe3c632Sopenharmony_ci * if no message id is specified. For non-response messages, 0. 343ffe3c632Sopenharmony_ci * @param {number} suggestedPivot The field number at which to start putting 344ffe3c632Sopenharmony_ci * fields into the extension object. This is only used if data does not 345ffe3c632Sopenharmony_ci * contain an extension object already. -1 if no extension object is 346ffe3c632Sopenharmony_ci * required for this message type. 347ffe3c632Sopenharmony_ci * @param {Array<number>} repeatedFields The message's repeated fields. 348ffe3c632Sopenharmony_ci * @param {Array<!Array<number>>=} opt_oneofFields The fields belonging to 349ffe3c632Sopenharmony_ci * each of the message's oneof unions. 350ffe3c632Sopenharmony_ci * @protected 351ffe3c632Sopenharmony_ci */ 352ffe3c632Sopenharmony_cijspb.Message.initialize = function( 353ffe3c632Sopenharmony_ci msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) { 354ffe3c632Sopenharmony_ci msg.wrappers_ = null; 355ffe3c632Sopenharmony_ci if (!data) { 356ffe3c632Sopenharmony_ci data = messageId ? [messageId] : []; 357ffe3c632Sopenharmony_ci } 358ffe3c632Sopenharmony_ci msg.messageId_ = messageId ? String(messageId) : undefined; 359ffe3c632Sopenharmony_ci // If the messageId is 0, this message is not a response message, so we shift 360ffe3c632Sopenharmony_ci // array indices down by 1 so as not to waste the first position in the array, 361ffe3c632Sopenharmony_ci // which would otherwise go unused. 362ffe3c632Sopenharmony_ci msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0; 363ffe3c632Sopenharmony_ci msg.array = data; 364ffe3c632Sopenharmony_ci jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot); 365ffe3c632Sopenharmony_ci msg.convertedPrimitiveFields_ = {}; 366ffe3c632Sopenharmony_ci 367ffe3c632Sopenharmony_ci if (!jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS) { 368ffe3c632Sopenharmony_ci // TODO(jakubvrana): This is same for all instances, move to prototype. 369ffe3c632Sopenharmony_ci // TODO(jakubvrana): There are indexOf calls on this in serialization, 370ffe3c632Sopenharmony_ci // consider switching to a set. 371ffe3c632Sopenharmony_ci msg.repeatedFields = repeatedFields; 372ffe3c632Sopenharmony_ci } 373ffe3c632Sopenharmony_ci 374ffe3c632Sopenharmony_ci if (repeatedFields) { 375ffe3c632Sopenharmony_ci for (var i = 0; i < repeatedFields.length; i++) { 376ffe3c632Sopenharmony_ci var fieldNumber = repeatedFields[i]; 377ffe3c632Sopenharmony_ci if (fieldNumber < msg.pivot_) { 378ffe3c632Sopenharmony_ci var index = jspb.Message.getIndex_(msg, fieldNumber); 379ffe3c632Sopenharmony_ci msg.array[index] = 380ffe3c632Sopenharmony_ci msg.array[index] || jspb.Message.EMPTY_LIST_SENTINEL_; 381ffe3c632Sopenharmony_ci } else { 382ffe3c632Sopenharmony_ci jspb.Message.maybeInitEmptyExtensionObject_(msg); 383ffe3c632Sopenharmony_ci msg.extensionObject_[fieldNumber] = msg.extensionObject_[fieldNumber] || 384ffe3c632Sopenharmony_ci jspb.Message.EMPTY_LIST_SENTINEL_; 385ffe3c632Sopenharmony_ci } 386ffe3c632Sopenharmony_ci } 387ffe3c632Sopenharmony_ci } 388ffe3c632Sopenharmony_ci 389ffe3c632Sopenharmony_ci if (opt_oneofFields && opt_oneofFields.length) { 390ffe3c632Sopenharmony_ci // Compute the oneof case for each union. This ensures only one value is 391ffe3c632Sopenharmony_ci // set in the union. 392ffe3c632Sopenharmony_ci for (var i = 0; i < opt_oneofFields.length; i++) { 393ffe3c632Sopenharmony_ci jspb.Message.computeOneofCase(msg, opt_oneofFields[i]); 394ffe3c632Sopenharmony_ci } 395ffe3c632Sopenharmony_ci } 396ffe3c632Sopenharmony_ci}; 397ffe3c632Sopenharmony_ci 398ffe3c632Sopenharmony_ci 399ffe3c632Sopenharmony_ci/** 400ffe3c632Sopenharmony_ci * Used to mark empty repeated fields. Serializes to null when serialized 401ffe3c632Sopenharmony_ci * to JSON. 402ffe3c632Sopenharmony_ci * When reading a repeated field readers must check the return value against 403ffe3c632Sopenharmony_ci * this value and return and replace it with a new empty array if it is 404ffe3c632Sopenharmony_ci * present. 405ffe3c632Sopenharmony_ci * @private @const {!Object} 406ffe3c632Sopenharmony_ci */ 407ffe3c632Sopenharmony_cijspb.Message.EMPTY_LIST_SENTINEL_ = goog.DEBUG && Object.freeze ? 408ffe3c632Sopenharmony_ci Object.freeze([]) : 409ffe3c632Sopenharmony_ci []; 410ffe3c632Sopenharmony_ci 411ffe3c632Sopenharmony_ci 412ffe3c632Sopenharmony_ci/** 413ffe3c632Sopenharmony_ci * Returns true if the provided argument is an array. 414ffe3c632Sopenharmony_ci * @param {*} o The object to classify as array or not. 415ffe3c632Sopenharmony_ci * @return {boolean} True if the provided object is an array. 416ffe3c632Sopenharmony_ci * @private 417ffe3c632Sopenharmony_ci */ 418ffe3c632Sopenharmony_cijspb.Message.isArray_ = function(o) { 419ffe3c632Sopenharmony_ci return jspb.Message.ASSUME_LOCAL_ARRAYS ? o instanceof Array : 420ffe3c632Sopenharmony_ci Array.isArray(o); 421ffe3c632Sopenharmony_ci}; 422ffe3c632Sopenharmony_ci 423ffe3c632Sopenharmony_ci/** 424ffe3c632Sopenharmony_ci * Returns true if the provided argument is an extension object. 425ffe3c632Sopenharmony_ci * @param {*} o The object to classify as array or not. 426ffe3c632Sopenharmony_ci * @return {boolean} True if the provided object is an extension object. 427ffe3c632Sopenharmony_ci * @private 428ffe3c632Sopenharmony_ci */ 429ffe3c632Sopenharmony_cijspb.Message.isExtensionObject_ = function(o) { 430ffe3c632Sopenharmony_ci // Normal fields are never objects, so we can be sure that if we find an 431ffe3c632Sopenharmony_ci // object here, then it's the extension object. However, we must ensure that 432ffe3c632Sopenharmony_ci // the object is not an array, since arrays are valid field values (bytes 433ffe3c632Sopenharmony_ci // fields can also be array). 434ffe3c632Sopenharmony_ci // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug 435ffe3c632Sopenharmony_ci // in Safari on iOS 8. See the description of CL/86511464 for details. 436ffe3c632Sopenharmony_ci return (o !== null && typeof o == 'object' && 437ffe3c632Sopenharmony_ci !jspb.Message.isArray_(o) && 438ffe3c632Sopenharmony_ci !(jspb.Message.SUPPORTS_UINT8ARRAY_ && o instanceof Uint8Array)); 439ffe3c632Sopenharmony_ci}; 440ffe3c632Sopenharmony_ci 441ffe3c632Sopenharmony_ci 442ffe3c632Sopenharmony_ci/** 443ffe3c632Sopenharmony_ci * If the array contains an extension object in its last position, then the 444ffe3c632Sopenharmony_ci * object is kept in place and its position is used as the pivot. If not, 445ffe3c632Sopenharmony_ci * decides the pivot of the message based on suggestedPivot without 446ffe3c632Sopenharmony_ci * materializing the extension object. 447ffe3c632Sopenharmony_ci * 448ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg The JsPb proto to modify. 449ffe3c632Sopenharmony_ci * @param {number} suggestedPivot See description for initialize(). 450ffe3c632Sopenharmony_ci * @private 451ffe3c632Sopenharmony_ci */ 452ffe3c632Sopenharmony_cijspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) { 453ffe3c632Sopenharmony_ci // There are 3 variants that need to be dealt with which are the 454ffe3c632Sopenharmony_ci // combination of whether there exists an extension object (EO) and 455ffe3c632Sopenharmony_ci // whether there is a suggested pivot (SP). 456ffe3c632Sopenharmony_ci // 457ffe3c632Sopenharmony_ci // EO, ? : pivot is the index of the EO 458ffe3c632Sopenharmony_ci // no-EO, no-SP: pivot is MAX_INT 459ffe3c632Sopenharmony_ci // no-EO, SP : pivot is the max(lastindex + 1, SP) 460ffe3c632Sopenharmony_ci 461ffe3c632Sopenharmony_ci var msgLength = msg.array.length; 462ffe3c632Sopenharmony_ci var lastIndex = -1; 463ffe3c632Sopenharmony_ci if (msgLength) { 464ffe3c632Sopenharmony_ci lastIndex = msgLength - 1; 465ffe3c632Sopenharmony_ci var obj = msg.array[lastIndex]; 466ffe3c632Sopenharmony_ci if (jspb.Message.isExtensionObject_(obj)) { 467ffe3c632Sopenharmony_ci msg.pivot_ = jspb.Message.getFieldNumber_(msg, lastIndex); 468ffe3c632Sopenharmony_ci msg.extensionObject_ = obj; 469ffe3c632Sopenharmony_ci return; 470ffe3c632Sopenharmony_ci } 471ffe3c632Sopenharmony_ci } 472ffe3c632Sopenharmony_ci 473ffe3c632Sopenharmony_ci if (suggestedPivot > -1) { 474ffe3c632Sopenharmony_ci // If a extension object is not present, set the pivot value as being 475ffe3c632Sopenharmony_ci // after the last value in the array to avoid overwriting values, etc. 476ffe3c632Sopenharmony_ci msg.pivot_ = Math.max( 477ffe3c632Sopenharmony_ci suggestedPivot, jspb.Message.getFieldNumber_(msg, lastIndex + 1)); 478ffe3c632Sopenharmony_ci // Avoid changing the shape of the proto with an empty extension object by 479ffe3c632Sopenharmony_ci // deferring the materialization of the extension object until the first 480ffe3c632Sopenharmony_ci // time a field set into it (may be due to getting a repeated proto field 481ffe3c632Sopenharmony_ci // from it, in which case a new empty array is set into it at first). 482ffe3c632Sopenharmony_ci msg.extensionObject_ = null; 483ffe3c632Sopenharmony_ci } else { 484ffe3c632Sopenharmony_ci // suggestedPivot is -1, which means that we don't have an extension object 485ffe3c632Sopenharmony_ci // at all, in which case all fields are stored in the array. 486ffe3c632Sopenharmony_ci msg.pivot_ = Number.MAX_VALUE; 487ffe3c632Sopenharmony_ci } 488ffe3c632Sopenharmony_ci}; 489ffe3c632Sopenharmony_ci 490ffe3c632Sopenharmony_ci 491ffe3c632Sopenharmony_ci/** 492ffe3c632Sopenharmony_ci * Creates an empty extensionObject_ if non exists. 493ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg The JsPb proto to modify. 494ffe3c632Sopenharmony_ci * @private 495ffe3c632Sopenharmony_ci */ 496ffe3c632Sopenharmony_cijspb.Message.maybeInitEmptyExtensionObject_ = function(msg) { 497ffe3c632Sopenharmony_ci var pivotIndex = jspb.Message.getIndex_(msg, msg.pivot_); 498ffe3c632Sopenharmony_ci if (!msg.array[pivotIndex]) { 499ffe3c632Sopenharmony_ci msg.extensionObject_ = msg.array[pivotIndex] = {}; 500ffe3c632Sopenharmony_ci } 501ffe3c632Sopenharmony_ci}; 502ffe3c632Sopenharmony_ci 503ffe3c632Sopenharmony_ci 504ffe3c632Sopenharmony_ci/** 505ffe3c632Sopenharmony_ci * Converts a JsPb repeated message field into an object list. 506ffe3c632Sopenharmony_ci * @param {!Array<T>} field The repeated message field to be 507ffe3c632Sopenharmony_ci * converted. 508ffe3c632Sopenharmony_ci * @param {?function(boolean=): Object| 509ffe3c632Sopenharmony_ci * function((boolean|undefined),T): Object} toObjectFn The toObject 510ffe3c632Sopenharmony_ci * function for this field. We need to pass this for effective dead code 511ffe3c632Sopenharmony_ci * removal. 512ffe3c632Sopenharmony_ci * @param {boolean=} opt_includeInstance Whether to include the JSPB instance 513ffe3c632Sopenharmony_ci * for transitional soy proto support: http://goto/soy-param-migration 514ffe3c632Sopenharmony_ci * @return {!Array<Object>} An array of converted message objects. 515ffe3c632Sopenharmony_ci * @template T 516ffe3c632Sopenharmony_ci */ 517ffe3c632Sopenharmony_cijspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) { 518ffe3c632Sopenharmony_ci // Not using goog.array.map in the generated code to keep it small. 519ffe3c632Sopenharmony_ci // And not using it here to avoid a function call. 520ffe3c632Sopenharmony_ci var result = []; 521ffe3c632Sopenharmony_ci for (var i = 0; i < field.length; i++) { 522ffe3c632Sopenharmony_ci result[i] = toObjectFn.call(field[i], opt_includeInstance, field[i]); 523ffe3c632Sopenharmony_ci } 524ffe3c632Sopenharmony_ci return result; 525ffe3c632Sopenharmony_ci}; 526ffe3c632Sopenharmony_ci 527ffe3c632Sopenharmony_ci 528ffe3c632Sopenharmony_ci/** 529ffe3c632Sopenharmony_ci * Adds a proto's extension data to a Soy rendering object. 530ffe3c632Sopenharmony_ci * @param {!jspb.Message} proto The proto whose extensions to convert. 531ffe3c632Sopenharmony_ci * @param {!Object} obj The Soy object to add converted extension data to. 532ffe3c632Sopenharmony_ci * @param {!Object} extensions The proto class' registered extensions. 533ffe3c632Sopenharmony_ci * @param {function(this:?, jspb.ExtensionFieldInfo) : *} getExtensionFn 534ffe3c632Sopenharmony_ci * The proto class' getExtension function. Passed for effective dead code 535ffe3c632Sopenharmony_ci * removal. 536ffe3c632Sopenharmony_ci * @param {boolean=} opt_includeInstance Whether to include the JSPB instance 537ffe3c632Sopenharmony_ci * for transitional soy proto support: http://goto/soy-param-migration 538ffe3c632Sopenharmony_ci */ 539ffe3c632Sopenharmony_cijspb.Message.toObjectExtension = function(proto, obj, extensions, 540ffe3c632Sopenharmony_ci getExtensionFn, opt_includeInstance) { 541ffe3c632Sopenharmony_ci for (var fieldNumber in extensions) { 542ffe3c632Sopenharmony_ci var fieldInfo = extensions[fieldNumber]; 543ffe3c632Sopenharmony_ci var value = getExtensionFn.call(proto, fieldInfo); 544ffe3c632Sopenharmony_ci if (value != null) { 545ffe3c632Sopenharmony_ci for (var name in fieldInfo.fieldName) { 546ffe3c632Sopenharmony_ci if (fieldInfo.fieldName.hasOwnProperty(name)) { 547ffe3c632Sopenharmony_ci break; // the compiled field name 548ffe3c632Sopenharmony_ci } 549ffe3c632Sopenharmony_ci } 550ffe3c632Sopenharmony_ci if (!fieldInfo.toObjectFn) { 551ffe3c632Sopenharmony_ci obj[name] = value; 552ffe3c632Sopenharmony_ci } else { 553ffe3c632Sopenharmony_ci if (fieldInfo.isRepeated) { 554ffe3c632Sopenharmony_ci obj[name] = jspb.Message.toObjectList( 555ffe3c632Sopenharmony_ci /** @type {!Array<!jspb.Message>} */ (value), 556ffe3c632Sopenharmony_ci fieldInfo.toObjectFn, opt_includeInstance); 557ffe3c632Sopenharmony_ci } else { 558ffe3c632Sopenharmony_ci obj[name] = fieldInfo.toObjectFn( 559ffe3c632Sopenharmony_ci opt_includeInstance, /** @type {!jspb.Message} */ (value)); 560ffe3c632Sopenharmony_ci } 561ffe3c632Sopenharmony_ci } 562ffe3c632Sopenharmony_ci } 563ffe3c632Sopenharmony_ci } 564ffe3c632Sopenharmony_ci}; 565ffe3c632Sopenharmony_ci 566ffe3c632Sopenharmony_ci 567ffe3c632Sopenharmony_ci/** 568ffe3c632Sopenharmony_ci * Writes a proto's extension data to a binary-format output stream. 569ffe3c632Sopenharmony_ci * @param {!jspb.Message} proto The proto whose extensions to convert. 570ffe3c632Sopenharmony_ci * @param {*} writer The binary-format writer to write to. 571ffe3c632Sopenharmony_ci * @param {!Object} extensions The proto class' registered extensions. 572ffe3c632Sopenharmony_ci * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo) : *} getExtensionFn The proto 573ffe3c632Sopenharmony_ci * class' getExtension function. Passed for effective dead code removal. 574ffe3c632Sopenharmony_ci */ 575ffe3c632Sopenharmony_cijspb.Message.serializeBinaryExtensions = function(proto, writer, extensions, 576ffe3c632Sopenharmony_ci getExtensionFn) { 577ffe3c632Sopenharmony_ci for (var fieldNumber in extensions) { 578ffe3c632Sopenharmony_ci var binaryFieldInfo = extensions[fieldNumber]; 579ffe3c632Sopenharmony_ci var fieldInfo = binaryFieldInfo.fieldInfo; 580ffe3c632Sopenharmony_ci 581ffe3c632Sopenharmony_ci // The old codegen doesn't add the extra fields to ExtensionFieldInfo, so we 582ffe3c632Sopenharmony_ci // need to gracefully error-out here rather than produce a null dereference 583ffe3c632Sopenharmony_ci // below. 584ffe3c632Sopenharmony_ci if (!binaryFieldInfo.binaryWriterFn) { 585ffe3c632Sopenharmony_ci throw new Error('Message extension present that was generated ' + 586ffe3c632Sopenharmony_ci 'without binary serialization support'); 587ffe3c632Sopenharmony_ci } 588ffe3c632Sopenharmony_ci var value = getExtensionFn.call(proto, fieldInfo); 589ffe3c632Sopenharmony_ci if (value != null) { 590ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 591ffe3c632Sopenharmony_ci // If the message type of the extension was generated without binary 592ffe3c632Sopenharmony_ci // support, there may not be a binary message serializer function, and 593ffe3c632Sopenharmony_ci // we can't know when we codegen the extending message that the extended 594ffe3c632Sopenharmony_ci // message may require binary support, so we can *only* catch this error 595ffe3c632Sopenharmony_ci // here, at runtime (and this decoupled codegen is the whole point of 596ffe3c632Sopenharmony_ci // extensions!). 597ffe3c632Sopenharmony_ci if (binaryFieldInfo.binaryMessageSerializeFn) { 598ffe3c632Sopenharmony_ci binaryFieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex, 599ffe3c632Sopenharmony_ci value, binaryFieldInfo.binaryMessageSerializeFn); 600ffe3c632Sopenharmony_ci } else { 601ffe3c632Sopenharmony_ci throw new Error('Message extension present holding submessage ' + 602ffe3c632Sopenharmony_ci 'without binary support enabled, and message is ' + 603ffe3c632Sopenharmony_ci 'being serialized to binary format'); 604ffe3c632Sopenharmony_ci } 605ffe3c632Sopenharmony_ci } else { 606ffe3c632Sopenharmony_ci binaryFieldInfo.binaryWriterFn.call( 607ffe3c632Sopenharmony_ci writer, fieldInfo.fieldIndex, value); 608ffe3c632Sopenharmony_ci } 609ffe3c632Sopenharmony_ci } 610ffe3c632Sopenharmony_ci } 611ffe3c632Sopenharmony_ci}; 612ffe3c632Sopenharmony_ci 613ffe3c632Sopenharmony_ci 614ffe3c632Sopenharmony_ci/** 615ffe3c632Sopenharmony_ci * Reads an extension field from the given reader and, if a valid extension, 616ffe3c632Sopenharmony_ci * sets the extension value. 617ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 618ffe3c632Sopenharmony_ci * @param {!jspb.BinaryReader} reader 619ffe3c632Sopenharmony_ci * @param {!Object} extensions The extensions object. 620ffe3c632Sopenharmony_ci * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo)} getExtensionFn 621ffe3c632Sopenharmony_ci * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo, ?)} setExtensionFn 622ffe3c632Sopenharmony_ci */ 623ffe3c632Sopenharmony_cijspb.Message.readBinaryExtension = function(msg, reader, extensions, 624ffe3c632Sopenharmony_ci getExtensionFn, setExtensionFn) { 625ffe3c632Sopenharmony_ci var binaryFieldInfo = extensions[reader.getFieldNumber()]; 626ffe3c632Sopenharmony_ci if (!binaryFieldInfo) { 627ffe3c632Sopenharmony_ci reader.skipField(); 628ffe3c632Sopenharmony_ci return; 629ffe3c632Sopenharmony_ci } 630ffe3c632Sopenharmony_ci var fieldInfo = binaryFieldInfo.fieldInfo; 631ffe3c632Sopenharmony_ci if (!binaryFieldInfo.binaryReaderFn) { 632ffe3c632Sopenharmony_ci throw new Error('Deserializing extension whose generated code does not ' + 633ffe3c632Sopenharmony_ci 'support binary format'); 634ffe3c632Sopenharmony_ci } 635ffe3c632Sopenharmony_ci 636ffe3c632Sopenharmony_ci var value; 637ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 638ffe3c632Sopenharmony_ci value = new fieldInfo.ctor(); 639ffe3c632Sopenharmony_ci binaryFieldInfo.binaryReaderFn.call( 640ffe3c632Sopenharmony_ci reader, value, binaryFieldInfo.binaryMessageDeserializeFn); 641ffe3c632Sopenharmony_ci } else { 642ffe3c632Sopenharmony_ci // All other types. 643ffe3c632Sopenharmony_ci value = binaryFieldInfo.binaryReaderFn.call(reader); 644ffe3c632Sopenharmony_ci } 645ffe3c632Sopenharmony_ci 646ffe3c632Sopenharmony_ci if (fieldInfo.isRepeated && !binaryFieldInfo.isPacked) { 647ffe3c632Sopenharmony_ci var currentList = getExtensionFn.call(msg, fieldInfo); 648ffe3c632Sopenharmony_ci if (!currentList) { 649ffe3c632Sopenharmony_ci setExtensionFn.call(msg, fieldInfo, [value]); 650ffe3c632Sopenharmony_ci } else { 651ffe3c632Sopenharmony_ci currentList.push(value); 652ffe3c632Sopenharmony_ci } 653ffe3c632Sopenharmony_ci } else { 654ffe3c632Sopenharmony_ci setExtensionFn.call(msg, fieldInfo, value); 655ffe3c632Sopenharmony_ci } 656ffe3c632Sopenharmony_ci}; 657ffe3c632Sopenharmony_ci 658ffe3c632Sopenharmony_ci 659ffe3c632Sopenharmony_ci/** 660ffe3c632Sopenharmony_ci * Gets the value of a non-extension field. 661ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 662ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 663ffe3c632Sopenharmony_ci * @return {string|number|boolean|Uint8Array|Array|null|undefined} 664ffe3c632Sopenharmony_ci * The field's value. 665ffe3c632Sopenharmony_ci * @protected 666ffe3c632Sopenharmony_ci */ 667ffe3c632Sopenharmony_cijspb.Message.getField = function(msg, fieldNumber) { 668ffe3c632Sopenharmony_ci if (fieldNumber < msg.pivot_) { 669ffe3c632Sopenharmony_ci var index = jspb.Message.getIndex_(msg, fieldNumber); 670ffe3c632Sopenharmony_ci var val = msg.array[index]; 671ffe3c632Sopenharmony_ci if (val === jspb.Message.EMPTY_LIST_SENTINEL_) { 672ffe3c632Sopenharmony_ci return msg.array[index] = []; 673ffe3c632Sopenharmony_ci } 674ffe3c632Sopenharmony_ci return val; 675ffe3c632Sopenharmony_ci } else { 676ffe3c632Sopenharmony_ci if (!msg.extensionObject_) { 677ffe3c632Sopenharmony_ci return undefined; 678ffe3c632Sopenharmony_ci } 679ffe3c632Sopenharmony_ci var val = msg.extensionObject_[fieldNumber]; 680ffe3c632Sopenharmony_ci if (val === jspb.Message.EMPTY_LIST_SENTINEL_) { 681ffe3c632Sopenharmony_ci return msg.extensionObject_[fieldNumber] = []; 682ffe3c632Sopenharmony_ci } 683ffe3c632Sopenharmony_ci return val; 684ffe3c632Sopenharmony_ci } 685ffe3c632Sopenharmony_ci}; 686ffe3c632Sopenharmony_ci 687ffe3c632Sopenharmony_ci 688ffe3c632Sopenharmony_ci/** 689ffe3c632Sopenharmony_ci * Gets the value of a non-extension repeated field. 690ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 691ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 692ffe3c632Sopenharmony_ci * @return {!Array} 693ffe3c632Sopenharmony_ci * The field's value. 694ffe3c632Sopenharmony_ci * @protected 695ffe3c632Sopenharmony_ci */ 696ffe3c632Sopenharmony_cijspb.Message.getRepeatedField = function(msg, fieldNumber) { 697ffe3c632Sopenharmony_ci return /** @type {!Array} */ (jspb.Message.getField(msg, fieldNumber)); 698ffe3c632Sopenharmony_ci}; 699ffe3c632Sopenharmony_ci 700ffe3c632Sopenharmony_ci 701ffe3c632Sopenharmony_ci/** 702ffe3c632Sopenharmony_ci * Gets the value of an optional float or double field. 703ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 704ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 705ffe3c632Sopenharmony_ci * @return {?number|undefined} The field's value. 706ffe3c632Sopenharmony_ci * @protected 707ffe3c632Sopenharmony_ci */ 708ffe3c632Sopenharmony_cijspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) { 709ffe3c632Sopenharmony_ci var value = jspb.Message.getField(msg, fieldNumber); 710ffe3c632Sopenharmony_ci // Converts "NaN", "Infinity" and "-Infinity" to their corresponding numbers. 711ffe3c632Sopenharmony_ci return value == null ? value : +value; 712ffe3c632Sopenharmony_ci}; 713ffe3c632Sopenharmony_ci 714ffe3c632Sopenharmony_ci 715ffe3c632Sopenharmony_ci/** 716ffe3c632Sopenharmony_ci * Gets the value of an optional boolean field. 717ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 718ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 719ffe3c632Sopenharmony_ci * @return {?boolean|undefined} The field's value. 720ffe3c632Sopenharmony_ci * @protected 721ffe3c632Sopenharmony_ci */ 722ffe3c632Sopenharmony_cijspb.Message.getBooleanField = function(msg, fieldNumber) { 723ffe3c632Sopenharmony_ci var value = jspb.Message.getField(msg, fieldNumber); 724ffe3c632Sopenharmony_ci // TODO(b/122673075): always return null when the value is null-ish. 725ffe3c632Sopenharmony_ci return value == null ? (value) : !!value; 726ffe3c632Sopenharmony_ci}; 727ffe3c632Sopenharmony_ci 728ffe3c632Sopenharmony_ci 729ffe3c632Sopenharmony_ci/** 730ffe3c632Sopenharmony_ci * Gets the value of a repeated float or double field. 731ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 732ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 733ffe3c632Sopenharmony_ci * @return {!Array<number>} The field's value. 734ffe3c632Sopenharmony_ci * @protected 735ffe3c632Sopenharmony_ci */ 736ffe3c632Sopenharmony_cijspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) { 737ffe3c632Sopenharmony_ci var values = jspb.Message.getRepeatedField(msg, fieldNumber); 738ffe3c632Sopenharmony_ci if (!msg.convertedPrimitiveFields_) { 739ffe3c632Sopenharmony_ci msg.convertedPrimitiveFields_ = {}; 740ffe3c632Sopenharmony_ci } 741ffe3c632Sopenharmony_ci if (!msg.convertedPrimitiveFields_[fieldNumber]) { 742ffe3c632Sopenharmony_ci for (var i = 0; i < values.length; i++) { 743ffe3c632Sopenharmony_ci // Converts "NaN", "Infinity" and "-Infinity" to their corresponding 744ffe3c632Sopenharmony_ci // numbers. 745ffe3c632Sopenharmony_ci values[i] = +values[i]; 746ffe3c632Sopenharmony_ci } 747ffe3c632Sopenharmony_ci msg.convertedPrimitiveFields_[fieldNumber] = true; 748ffe3c632Sopenharmony_ci } 749ffe3c632Sopenharmony_ci return /** @type {!Array<number>} */ (values); 750ffe3c632Sopenharmony_ci}; 751ffe3c632Sopenharmony_ci 752ffe3c632Sopenharmony_ci/** 753ffe3c632Sopenharmony_ci * Gets the value of a repeated boolean field. 754ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 755ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 756ffe3c632Sopenharmony_ci * @return {!Array<boolean>} The field's value. 757ffe3c632Sopenharmony_ci * @protected 758ffe3c632Sopenharmony_ci */ 759ffe3c632Sopenharmony_cijspb.Message.getRepeatedBooleanField = function(msg, fieldNumber) { 760ffe3c632Sopenharmony_ci var values = jspb.Message.getRepeatedField(msg, fieldNumber); 761ffe3c632Sopenharmony_ci if (!msg.convertedPrimitiveFields_) { 762ffe3c632Sopenharmony_ci msg.convertedPrimitiveFields_ = {}; 763ffe3c632Sopenharmony_ci } 764ffe3c632Sopenharmony_ci if (!msg.convertedPrimitiveFields_[fieldNumber]) { 765ffe3c632Sopenharmony_ci for (var i = 0; i < values.length; i++) { 766ffe3c632Sopenharmony_ci // Converts 0 and 1 to their corresponding booleans. 767ffe3c632Sopenharmony_ci values[i] = !!values[i]; 768ffe3c632Sopenharmony_ci } 769ffe3c632Sopenharmony_ci msg.convertedPrimitiveFields_[fieldNumber] = true; 770ffe3c632Sopenharmony_ci } 771ffe3c632Sopenharmony_ci return /** @type {!Array<boolean>} */ (values); 772ffe3c632Sopenharmony_ci}; 773ffe3c632Sopenharmony_ci 774ffe3c632Sopenharmony_ci 775ffe3c632Sopenharmony_ci/** 776ffe3c632Sopenharmony_ci * Coerce a 'bytes' field to a base 64 string. 777ffe3c632Sopenharmony_ci * @param {string|Uint8Array|null} value 778ffe3c632Sopenharmony_ci * @return {?string} The field's coerced value. 779ffe3c632Sopenharmony_ci */ 780ffe3c632Sopenharmony_cijspb.Message.bytesAsB64 = function(value) { 781ffe3c632Sopenharmony_ci if (value == null || typeof value === 'string') { 782ffe3c632Sopenharmony_ci return value; 783ffe3c632Sopenharmony_ci } 784ffe3c632Sopenharmony_ci if (jspb.Message.SUPPORTS_UINT8ARRAY_ && value instanceof Uint8Array) { 785ffe3c632Sopenharmony_ci return goog.crypt.base64.encodeByteArray(value); 786ffe3c632Sopenharmony_ci } 787ffe3c632Sopenharmony_ci goog.asserts.fail('Cannot coerce to b64 string: ' + goog.typeOf(value)); 788ffe3c632Sopenharmony_ci return null; 789ffe3c632Sopenharmony_ci}; 790ffe3c632Sopenharmony_ci 791ffe3c632Sopenharmony_ci 792ffe3c632Sopenharmony_ci/** 793ffe3c632Sopenharmony_ci * Coerce a 'bytes' field to a Uint8Array byte buffer. 794ffe3c632Sopenharmony_ci * Note that Uint8Array is not supported on IE versions before 10 nor on Opera 795ffe3c632Sopenharmony_ci * Mini. @see http://caniuse.com/Uint8Array 796ffe3c632Sopenharmony_ci * @param {string|Uint8Array|null} value 797ffe3c632Sopenharmony_ci * @return {?Uint8Array} The field's coerced value. 798ffe3c632Sopenharmony_ci */ 799ffe3c632Sopenharmony_cijspb.Message.bytesAsU8 = function(value) { 800ffe3c632Sopenharmony_ci if (value == null || value instanceof Uint8Array) { 801ffe3c632Sopenharmony_ci return value; 802ffe3c632Sopenharmony_ci } 803ffe3c632Sopenharmony_ci if (typeof value === 'string') { 804ffe3c632Sopenharmony_ci return goog.crypt.base64.decodeStringToUint8Array(value); 805ffe3c632Sopenharmony_ci } 806ffe3c632Sopenharmony_ci goog.asserts.fail('Cannot coerce to Uint8Array: ' + goog.typeOf(value)); 807ffe3c632Sopenharmony_ci return null; 808ffe3c632Sopenharmony_ci}; 809ffe3c632Sopenharmony_ci 810ffe3c632Sopenharmony_ci 811ffe3c632Sopenharmony_ci/** 812ffe3c632Sopenharmony_ci * Coerce a repeated 'bytes' field to an array of base 64 strings. 813ffe3c632Sopenharmony_ci * Note: the returned array should be treated as immutable. 814ffe3c632Sopenharmony_ci * @param {!Array<string>|!Array<!Uint8Array>} value 815ffe3c632Sopenharmony_ci * @return {!Array<string?>} The field's coerced value. 816ffe3c632Sopenharmony_ci */ 817ffe3c632Sopenharmony_cijspb.Message.bytesListAsB64 = function(value) { 818ffe3c632Sopenharmony_ci jspb.Message.assertConsistentTypes_(value); 819ffe3c632Sopenharmony_ci if (!value.length || typeof value[0] === 'string') { 820ffe3c632Sopenharmony_ci return /** @type {!Array<string>} */ (value); 821ffe3c632Sopenharmony_ci } 822ffe3c632Sopenharmony_ci return goog.array.map(value, jspb.Message.bytesAsB64); 823ffe3c632Sopenharmony_ci}; 824ffe3c632Sopenharmony_ci 825ffe3c632Sopenharmony_ci 826ffe3c632Sopenharmony_ci/** 827ffe3c632Sopenharmony_ci * Coerce a repeated 'bytes' field to an array of Uint8Array byte buffers. 828ffe3c632Sopenharmony_ci * Note: the returned array should be treated as immutable. 829ffe3c632Sopenharmony_ci * Note that Uint8Array is not supported on IE versions before 10 nor on Opera 830ffe3c632Sopenharmony_ci * Mini. @see http://caniuse.com/Uint8Array 831ffe3c632Sopenharmony_ci * @param {!Array<string>|!Array<!Uint8Array>} value 832ffe3c632Sopenharmony_ci * @return {!Array<Uint8Array?>} The field's coerced value. 833ffe3c632Sopenharmony_ci */ 834ffe3c632Sopenharmony_cijspb.Message.bytesListAsU8 = function(value) { 835ffe3c632Sopenharmony_ci jspb.Message.assertConsistentTypes_(value); 836ffe3c632Sopenharmony_ci if (!value.length || value[0] instanceof Uint8Array) { 837ffe3c632Sopenharmony_ci return /** @type {!Array<!Uint8Array>} */ (value); 838ffe3c632Sopenharmony_ci } 839ffe3c632Sopenharmony_ci return goog.array.map(value, jspb.Message.bytesAsU8); 840ffe3c632Sopenharmony_ci}; 841ffe3c632Sopenharmony_ci 842ffe3c632Sopenharmony_ci 843ffe3c632Sopenharmony_ci/** 844ffe3c632Sopenharmony_ci * Asserts that all elements of an array are of the same type. 845ffe3c632Sopenharmony_ci * @param {Array?} array The array to test. 846ffe3c632Sopenharmony_ci * @private 847ffe3c632Sopenharmony_ci */ 848ffe3c632Sopenharmony_cijspb.Message.assertConsistentTypes_ = function(array) { 849ffe3c632Sopenharmony_ci if (goog.DEBUG && array && array.length > 1) { 850ffe3c632Sopenharmony_ci var expected = goog.typeOf(array[0]); 851ffe3c632Sopenharmony_ci goog.array.forEach(array, function(e) { 852ffe3c632Sopenharmony_ci if (goog.typeOf(e) != expected) { 853ffe3c632Sopenharmony_ci goog.asserts.fail('Inconsistent type in JSPB repeated field array. ' + 854ffe3c632Sopenharmony_ci 'Got ' + goog.typeOf(e) + ' expected ' + expected); 855ffe3c632Sopenharmony_ci } 856ffe3c632Sopenharmony_ci }); 857ffe3c632Sopenharmony_ci } 858ffe3c632Sopenharmony_ci}; 859ffe3c632Sopenharmony_ci 860ffe3c632Sopenharmony_ci 861ffe3c632Sopenharmony_ci/** 862ffe3c632Sopenharmony_ci * Gets the value of a non-extension primitive field, with proto3 (non-nullable 863ffe3c632Sopenharmony_ci * primitives) semantics. Returns `defaultValue` if the field is not otherwise 864ffe3c632Sopenharmony_ci * set. 865ffe3c632Sopenharmony_ci * @template T 866ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 867ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 868ffe3c632Sopenharmony_ci * @param {T} defaultValue The default value. 869ffe3c632Sopenharmony_ci * @return {T} The field's value. 870ffe3c632Sopenharmony_ci * @protected 871ffe3c632Sopenharmony_ci */ 872ffe3c632Sopenharmony_cijspb.Message.getFieldWithDefault = function(msg, fieldNumber, defaultValue) { 873ffe3c632Sopenharmony_ci var value = jspb.Message.getField(msg, fieldNumber); 874ffe3c632Sopenharmony_ci if (value == null) { 875ffe3c632Sopenharmony_ci return defaultValue; 876ffe3c632Sopenharmony_ci } else { 877ffe3c632Sopenharmony_ci return value; 878ffe3c632Sopenharmony_ci } 879ffe3c632Sopenharmony_ci}; 880ffe3c632Sopenharmony_ci 881ffe3c632Sopenharmony_ci 882ffe3c632Sopenharmony_ci/** 883ffe3c632Sopenharmony_ci * Gets the value of a boolean field, with proto3 (non-nullable primitives) 884ffe3c632Sopenharmony_ci * semantics. Returns `defaultValue` if the field is not otherwise set. 885ffe3c632Sopenharmony_ci * @template T 886ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 887ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 888ffe3c632Sopenharmony_ci * @param {boolean} defaultValue The default value. 889ffe3c632Sopenharmony_ci * @return {boolean} The field's value. 890ffe3c632Sopenharmony_ci * @protected 891ffe3c632Sopenharmony_ci */ 892ffe3c632Sopenharmony_cijspb.Message.getBooleanFieldWithDefault = function( 893ffe3c632Sopenharmony_ci msg, fieldNumber, defaultValue) { 894ffe3c632Sopenharmony_ci var value = jspb.Message.getBooleanField(msg, fieldNumber); 895ffe3c632Sopenharmony_ci if (value == null) { 896ffe3c632Sopenharmony_ci return defaultValue; 897ffe3c632Sopenharmony_ci } else { 898ffe3c632Sopenharmony_ci return value; 899ffe3c632Sopenharmony_ci } 900ffe3c632Sopenharmony_ci}; 901ffe3c632Sopenharmony_ci 902ffe3c632Sopenharmony_ci 903ffe3c632Sopenharmony_ci/** 904ffe3c632Sopenharmony_ci * Gets the value of a floating point field, with proto3 (non-nullable 905ffe3c632Sopenharmony_ci * primitives) semantics. Returns `defaultValue` if the field is not otherwise 906ffe3c632Sopenharmony_ci * set. 907ffe3c632Sopenharmony_ci * @template T 908ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 909ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 910ffe3c632Sopenharmony_ci * @param {number} defaultValue The default value. 911ffe3c632Sopenharmony_ci * @return {number} The field's value. 912ffe3c632Sopenharmony_ci * @protected 913ffe3c632Sopenharmony_ci */ 914ffe3c632Sopenharmony_cijspb.Message.getFloatingPointFieldWithDefault = function( 915ffe3c632Sopenharmony_ci msg, fieldNumber, defaultValue) { 916ffe3c632Sopenharmony_ci var value = jspb.Message.getOptionalFloatingPointField(msg, fieldNumber); 917ffe3c632Sopenharmony_ci if (value == null) { 918ffe3c632Sopenharmony_ci return defaultValue; 919ffe3c632Sopenharmony_ci } else { 920ffe3c632Sopenharmony_ci return value; 921ffe3c632Sopenharmony_ci } 922ffe3c632Sopenharmony_ci}; 923ffe3c632Sopenharmony_ci 924ffe3c632Sopenharmony_ci 925ffe3c632Sopenharmony_ci/** 926ffe3c632Sopenharmony_ci * Alias for getFieldWithDefault used by older generated code. 927ffe3c632Sopenharmony_ci * @template T 928ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 929ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 930ffe3c632Sopenharmony_ci * @param {T} defaultValue The default value. 931ffe3c632Sopenharmony_ci * @return {T} The field's value. 932ffe3c632Sopenharmony_ci * @protected 933ffe3c632Sopenharmony_ci */ 934ffe3c632Sopenharmony_cijspb.Message.getFieldProto3 = jspb.Message.getFieldWithDefault; 935ffe3c632Sopenharmony_ci 936ffe3c632Sopenharmony_ci 937ffe3c632Sopenharmony_ci/** 938ffe3c632Sopenharmony_ci * Gets the value of a map field, lazily creating the map container if 939ffe3c632Sopenharmony_ci * necessary. 940ffe3c632Sopenharmony_ci * 941ffe3c632Sopenharmony_ci * This should only be called from generated code, because it requires knowledge 942ffe3c632Sopenharmony_ci * of serialization/parsing callbacks (which are required by the map at 943ffe3c632Sopenharmony_ci * construction time, and the map may be constructed here). 944ffe3c632Sopenharmony_ci * 945ffe3c632Sopenharmony_ci * @template K, V 946ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg 947ffe3c632Sopenharmony_ci * @param {number} fieldNumber 948ffe3c632Sopenharmony_ci * @param {boolean|undefined} noLazyCreate 949ffe3c632Sopenharmony_ci * @param {?=} opt_valueCtor 950ffe3c632Sopenharmony_ci * @return {!jspb.Map<K, V>|undefined} 951ffe3c632Sopenharmony_ci * @protected 952ffe3c632Sopenharmony_ci */ 953ffe3c632Sopenharmony_cijspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate, 954ffe3c632Sopenharmony_ci opt_valueCtor) { 955ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 956ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 957ffe3c632Sopenharmony_ci } 958ffe3c632Sopenharmony_ci // If we already have a map in the map wrappers, return that. 959ffe3c632Sopenharmony_ci if (fieldNumber in msg.wrappers_) { 960ffe3c632Sopenharmony_ci return msg.wrappers_[fieldNumber]; 961ffe3c632Sopenharmony_ci } 962ffe3c632Sopenharmony_ci var arr = jspb.Message.getField(msg, fieldNumber); 963ffe3c632Sopenharmony_ci // Wrap the underlying elements array with a Map. 964ffe3c632Sopenharmony_ci if (!arr) { 965ffe3c632Sopenharmony_ci if (noLazyCreate) { 966ffe3c632Sopenharmony_ci return undefined; 967ffe3c632Sopenharmony_ci } 968ffe3c632Sopenharmony_ci arr = []; 969ffe3c632Sopenharmony_ci jspb.Message.setField(msg, fieldNumber, arr); 970ffe3c632Sopenharmony_ci } 971ffe3c632Sopenharmony_ci return msg.wrappers_[fieldNumber] = 972ffe3c632Sopenharmony_ci new jspb.Map( 973ffe3c632Sopenharmony_ci /** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor); 974ffe3c632Sopenharmony_ci}; 975ffe3c632Sopenharmony_ci 976ffe3c632Sopenharmony_ci 977ffe3c632Sopenharmony_ci/** 978ffe3c632Sopenharmony_ci * Sets the value of a non-extension field. 979ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 980ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 981ffe3c632Sopenharmony_ci * @param {string|number|boolean|Uint8Array|Array|undefined} value New value 982ffe3c632Sopenharmony_ci * @return {T} return msg 983ffe3c632Sopenharmony_ci * @template T 984ffe3c632Sopenharmony_ci * @protected 985ffe3c632Sopenharmony_ci */ 986ffe3c632Sopenharmony_cijspb.Message.setField = function(msg, fieldNumber, value) { 987ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 988ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 989ffe3c632Sopenharmony_ci if (fieldNumber < msg.pivot_) { 990ffe3c632Sopenharmony_ci msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value; 991ffe3c632Sopenharmony_ci } else { 992ffe3c632Sopenharmony_ci jspb.Message.maybeInitEmptyExtensionObject_(msg); 993ffe3c632Sopenharmony_ci msg.extensionObject_[fieldNumber] = value; 994ffe3c632Sopenharmony_ci } 995ffe3c632Sopenharmony_ci return msg; 996ffe3c632Sopenharmony_ci}; 997ffe3c632Sopenharmony_ci 998ffe3c632Sopenharmony_ci 999ffe3c632Sopenharmony_ci/** 1000ffe3c632Sopenharmony_ci * Sets the value of a non-extension integer field of a proto3 1001ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1002ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1003ffe3c632Sopenharmony_ci * @param {number} value New value 1004ffe3c632Sopenharmony_ci * @return {T} return msg 1005ffe3c632Sopenharmony_ci * @template T 1006ffe3c632Sopenharmony_ci * @protected 1007ffe3c632Sopenharmony_ci */ 1008ffe3c632Sopenharmony_cijspb.Message.setProto3IntField = function(msg, fieldNumber, value) { 1009ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); 1010ffe3c632Sopenharmony_ci}; 1011ffe3c632Sopenharmony_ci 1012ffe3c632Sopenharmony_ci 1013ffe3c632Sopenharmony_ci/** 1014ffe3c632Sopenharmony_ci * Sets the value of a non-extension floating point field of a proto3 1015ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1016ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1017ffe3c632Sopenharmony_ci * @param {number} value New value 1018ffe3c632Sopenharmony_ci * @return {T} return msg 1019ffe3c632Sopenharmony_ci * @template T 1020ffe3c632Sopenharmony_ci * @protected 1021ffe3c632Sopenharmony_ci */ 1022ffe3c632Sopenharmony_cijspb.Message.setProto3FloatField = function(msg, fieldNumber, value) { 1023ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0); 1024ffe3c632Sopenharmony_ci}; 1025ffe3c632Sopenharmony_ci 1026ffe3c632Sopenharmony_ci 1027ffe3c632Sopenharmony_ci/** 1028ffe3c632Sopenharmony_ci * Sets the value of a non-extension boolean field of a proto3 1029ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1030ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1031ffe3c632Sopenharmony_ci * @param {boolean} value New value 1032ffe3c632Sopenharmony_ci * @return {T} return msg 1033ffe3c632Sopenharmony_ci * @template T 1034ffe3c632Sopenharmony_ci * @protected 1035ffe3c632Sopenharmony_ci */ 1036ffe3c632Sopenharmony_cijspb.Message.setProto3BooleanField = function(msg, fieldNumber, value) { 1037ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false); 1038ffe3c632Sopenharmony_ci}; 1039ffe3c632Sopenharmony_ci 1040ffe3c632Sopenharmony_ci 1041ffe3c632Sopenharmony_ci/** 1042ffe3c632Sopenharmony_ci * Sets the value of a non-extension String field of a proto3 1043ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1044ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1045ffe3c632Sopenharmony_ci * @param {string} value New value 1046ffe3c632Sopenharmony_ci * @return {T} return msg 1047ffe3c632Sopenharmony_ci * @template T 1048ffe3c632Sopenharmony_ci * @protected 1049ffe3c632Sopenharmony_ci */ 1050ffe3c632Sopenharmony_cijspb.Message.setProto3StringField = function(msg, fieldNumber, value) { 1051ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ''); 1052ffe3c632Sopenharmony_ci}; 1053ffe3c632Sopenharmony_ci 1054ffe3c632Sopenharmony_ci 1055ffe3c632Sopenharmony_ci/** 1056ffe3c632Sopenharmony_ci * Sets the value of a non-extension Bytes field of a proto3 1057ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1058ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1059ffe3c632Sopenharmony_ci * @param {!Uint8Array|string} value New value 1060ffe3c632Sopenharmony_ci * @return {T} return msg 1061ffe3c632Sopenharmony_ci * @template T 1062ffe3c632Sopenharmony_ci * @protected 1063ffe3c632Sopenharmony_ci */ 1064ffe3c632Sopenharmony_cijspb.Message.setProto3BytesField = function(msg, fieldNumber, value) { 1065ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ''); 1066ffe3c632Sopenharmony_ci}; 1067ffe3c632Sopenharmony_ci 1068ffe3c632Sopenharmony_ci 1069ffe3c632Sopenharmony_ci/** 1070ffe3c632Sopenharmony_ci * Sets the value of a non-extension enum field of a proto3 1071ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1072ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1073ffe3c632Sopenharmony_ci * @param {number} value New value 1074ffe3c632Sopenharmony_ci * @return {T} return msg 1075ffe3c632Sopenharmony_ci * @template T 1076ffe3c632Sopenharmony_ci * @protected 1077ffe3c632Sopenharmony_ci */ 1078ffe3c632Sopenharmony_cijspb.Message.setProto3EnumField = function(msg, fieldNumber, value) { 1079ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); 1080ffe3c632Sopenharmony_ci}; 1081ffe3c632Sopenharmony_ci 1082ffe3c632Sopenharmony_ci 1083ffe3c632Sopenharmony_ci/** 1084ffe3c632Sopenharmony_ci * Sets the value of a non-extension int field of a proto3 that has jstype set 1085ffe3c632Sopenharmony_ci * to String. 1086ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1087ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1088ffe3c632Sopenharmony_ci * @param {string} value New value 1089ffe3c632Sopenharmony_ci * @return {T} return msg 1090ffe3c632Sopenharmony_ci * @template T 1091ffe3c632Sopenharmony_ci * @protected 1092ffe3c632Sopenharmony_ci */ 1093ffe3c632Sopenharmony_cijspb.Message.setProto3StringIntField = function(msg, fieldNumber, value) { 1094ffe3c632Sopenharmony_ci return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '0'); 1095ffe3c632Sopenharmony_ci}; 1096ffe3c632Sopenharmony_ci 1097ffe3c632Sopenharmony_ci/** 1098ffe3c632Sopenharmony_ci * Sets the value of a non-extension primitive field, with proto3 (non-nullable 1099ffe3c632Sopenharmony_ci * primitives) semantics of ignoring values that are equal to the type's 1100ffe3c632Sopenharmony_ci * default. 1101ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1102ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1103ffe3c632Sopenharmony_ci * @param {!Uint8Array|string|number|boolean|undefined} value New value 1104ffe3c632Sopenharmony_ci * @param {!Uint8Array|string|number|boolean} defaultValue The default value. 1105ffe3c632Sopenharmony_ci * @return {T} return msg 1106ffe3c632Sopenharmony_ci * @template T 1107ffe3c632Sopenharmony_ci * @private 1108ffe3c632Sopenharmony_ci */ 1109ffe3c632Sopenharmony_cijspb.Message.setFieldIgnoringDefault_ = function( 1110ffe3c632Sopenharmony_ci msg, fieldNumber, value, defaultValue) { 1111ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1112ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1113ffe3c632Sopenharmony_ci if (value !== defaultValue) { 1114ffe3c632Sopenharmony_ci jspb.Message.setField(msg, fieldNumber, value); 1115ffe3c632Sopenharmony_ci } else if (fieldNumber < msg.pivot_) { 1116ffe3c632Sopenharmony_ci msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null; 1117ffe3c632Sopenharmony_ci } else { 1118ffe3c632Sopenharmony_ci jspb.Message.maybeInitEmptyExtensionObject_(msg); 1119ffe3c632Sopenharmony_ci delete msg.extensionObject_[fieldNumber]; 1120ffe3c632Sopenharmony_ci } 1121ffe3c632Sopenharmony_ci return msg; 1122ffe3c632Sopenharmony_ci}; 1123ffe3c632Sopenharmony_ci 1124ffe3c632Sopenharmony_ci 1125ffe3c632Sopenharmony_ci/** 1126ffe3c632Sopenharmony_ci * Adds a value to a repeated, primitive field. 1127ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1128ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1129ffe3c632Sopenharmony_ci * @param {string|number|boolean|!Uint8Array} value New value 1130ffe3c632Sopenharmony_ci * @param {number=} opt_index Index where to put new value. 1131ffe3c632Sopenharmony_ci * @return {T} return msg 1132ffe3c632Sopenharmony_ci * @template T 1133ffe3c632Sopenharmony_ci * @protected 1134ffe3c632Sopenharmony_ci */ 1135ffe3c632Sopenharmony_cijspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) { 1136ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1137ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1138ffe3c632Sopenharmony_ci var arr = jspb.Message.getRepeatedField(msg, fieldNumber); 1139ffe3c632Sopenharmony_ci if (opt_index != undefined) { 1140ffe3c632Sopenharmony_ci arr.splice(opt_index, 0, value); 1141ffe3c632Sopenharmony_ci } else { 1142ffe3c632Sopenharmony_ci arr.push(value); 1143ffe3c632Sopenharmony_ci } 1144ffe3c632Sopenharmony_ci return msg; 1145ffe3c632Sopenharmony_ci}; 1146ffe3c632Sopenharmony_ci 1147ffe3c632Sopenharmony_ci 1148ffe3c632Sopenharmony_ci/** 1149ffe3c632Sopenharmony_ci * Sets the value of a field in a oneof union and clears all other fields in 1150ffe3c632Sopenharmony_ci * the union. 1151ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1152ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1153ffe3c632Sopenharmony_ci * @param {!Array<number>} oneof The fields belonging to the union. 1154ffe3c632Sopenharmony_ci * @param {string|number|boolean|Uint8Array|Array|undefined} value New value 1155ffe3c632Sopenharmony_ci * @return {T} return msg 1156ffe3c632Sopenharmony_ci * @template T 1157ffe3c632Sopenharmony_ci * @protected 1158ffe3c632Sopenharmony_ci */ 1159ffe3c632Sopenharmony_cijspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) { 1160ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1161ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1162ffe3c632Sopenharmony_ci var currentCase = jspb.Message.computeOneofCase(msg, oneof); 1163ffe3c632Sopenharmony_ci if (currentCase && currentCase !== fieldNumber && value !== undefined) { 1164ffe3c632Sopenharmony_ci if (msg.wrappers_ && currentCase in msg.wrappers_) { 1165ffe3c632Sopenharmony_ci msg.wrappers_[currentCase] = undefined; 1166ffe3c632Sopenharmony_ci } 1167ffe3c632Sopenharmony_ci jspb.Message.setField(msg, currentCase, undefined); 1168ffe3c632Sopenharmony_ci } 1169ffe3c632Sopenharmony_ci return jspb.Message.setField(msg, fieldNumber, value); 1170ffe3c632Sopenharmony_ci}; 1171ffe3c632Sopenharmony_ci 1172ffe3c632Sopenharmony_ci 1173ffe3c632Sopenharmony_ci/** 1174ffe3c632Sopenharmony_ci * Computes the selection in a oneof group for the given message, ensuring 1175ffe3c632Sopenharmony_ci * only one field is set in the process. 1176ffe3c632Sopenharmony_ci * 1177ffe3c632Sopenharmony_ci * According to the protobuf language guide ( 1178ffe3c632Sopenharmony_ci * https://developers.google.com/protocol-buffers/docs/proto#oneof), "if the 1179ffe3c632Sopenharmony_ci * parser encounters multiple members of the same oneof on the wire, only the 1180ffe3c632Sopenharmony_ci * last member seen is used in the parsed message." Since JSPB serializes 1181ffe3c632Sopenharmony_ci * messages to a JSON array, the "last member seen" will always be the field 1182ffe3c632Sopenharmony_ci * with the greatest field number (directly corresponding to the greatest 1183ffe3c632Sopenharmony_ci * array index). 1184ffe3c632Sopenharmony_ci * 1185ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 1186ffe3c632Sopenharmony_ci * @param {!Array<number>} oneof The field numbers belonging to the union. 1187ffe3c632Sopenharmony_ci * @return {number} The field number currently set in the union, or 0 if none. 1188ffe3c632Sopenharmony_ci * @protected 1189ffe3c632Sopenharmony_ci */ 1190ffe3c632Sopenharmony_cijspb.Message.computeOneofCase = function(msg, oneof) { 1191ffe3c632Sopenharmony_ci var oneofField; 1192ffe3c632Sopenharmony_ci var oneofValue; 1193ffe3c632Sopenharmony_ci 1194ffe3c632Sopenharmony_ci for (var i = 0; i < oneof.length; i++) { 1195ffe3c632Sopenharmony_ci var fieldNumber = oneof[i]; 1196ffe3c632Sopenharmony_ci var value = jspb.Message.getField(msg, fieldNumber); 1197ffe3c632Sopenharmony_ci if (value != null) { 1198ffe3c632Sopenharmony_ci oneofField = fieldNumber; 1199ffe3c632Sopenharmony_ci oneofValue = value; 1200ffe3c632Sopenharmony_ci jspb.Message.setField(msg, fieldNumber, undefined); 1201ffe3c632Sopenharmony_ci } 1202ffe3c632Sopenharmony_ci } 1203ffe3c632Sopenharmony_ci 1204ffe3c632Sopenharmony_ci if (oneofField) { 1205ffe3c632Sopenharmony_ci // NB: We know the value is unique, so we can call jspb.Message.setField 1206ffe3c632Sopenharmony_ci // directly instead of jpsb.Message.setOneofField. Also, setOneofField 1207ffe3c632Sopenharmony_ci // calls this function. 1208ffe3c632Sopenharmony_ci jspb.Message.setField(msg, oneofField, oneofValue); 1209ffe3c632Sopenharmony_ci return oneofField; 1210ffe3c632Sopenharmony_ci } 1211ffe3c632Sopenharmony_ci 1212ffe3c632Sopenharmony_ci return 0; 1213ffe3c632Sopenharmony_ci}; 1214ffe3c632Sopenharmony_ci 1215ffe3c632Sopenharmony_ci 1216ffe3c632Sopenharmony_ci/** 1217ffe3c632Sopenharmony_ci * Gets and wraps a proto field on access. 1218ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 1219ffe3c632Sopenharmony_ci * @param {function(new:jspb.Message, Array)} ctor Constructor for the field. 1220ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1221ffe3c632Sopenharmony_ci * @param {number=} opt_required True (1) if this is a required field. 1222ffe3c632Sopenharmony_ci * @return {jspb.Message} The field as a jspb proto. 1223ffe3c632Sopenharmony_ci * @protected 1224ffe3c632Sopenharmony_ci */ 1225ffe3c632Sopenharmony_cijspb.Message.getWrapperField = function(msg, ctor, fieldNumber, opt_required) { 1226ffe3c632Sopenharmony_ci // TODO(mwr): Consider copying data and/or arrays. 1227ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 1228ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 1229ffe3c632Sopenharmony_ci } 1230ffe3c632Sopenharmony_ci if (!msg.wrappers_[fieldNumber]) { 1231ffe3c632Sopenharmony_ci var data = /** @type {Array} */ (jspb.Message.getField(msg, fieldNumber)); 1232ffe3c632Sopenharmony_ci if (opt_required || data) { 1233ffe3c632Sopenharmony_ci // TODO(mwr): Remove existence test for always valid default protos. 1234ffe3c632Sopenharmony_ci msg.wrappers_[fieldNumber] = new ctor(data); 1235ffe3c632Sopenharmony_ci } 1236ffe3c632Sopenharmony_ci } 1237ffe3c632Sopenharmony_ci return /** @type {jspb.Message} */ (msg.wrappers_[fieldNumber]); 1238ffe3c632Sopenharmony_ci}; 1239ffe3c632Sopenharmony_ci 1240ffe3c632Sopenharmony_ci 1241ffe3c632Sopenharmony_ci/** 1242ffe3c632Sopenharmony_ci * Gets and wraps a repeated proto field on access. 1243ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 1244ffe3c632Sopenharmony_ci * @param {function(new:jspb.Message, Array)} ctor Constructor for the field. 1245ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1246ffe3c632Sopenharmony_ci * @return {!Array<!jspb.Message>} The repeated field as an array of protos. 1247ffe3c632Sopenharmony_ci * @protected 1248ffe3c632Sopenharmony_ci */ 1249ffe3c632Sopenharmony_cijspb.Message.getRepeatedWrapperField = function(msg, ctor, fieldNumber) { 1250ffe3c632Sopenharmony_ci jspb.Message.wrapRepeatedField_(msg, ctor, fieldNumber); 1251ffe3c632Sopenharmony_ci var val = msg.wrappers_[fieldNumber]; 1252ffe3c632Sopenharmony_ci if (val == jspb.Message.EMPTY_LIST_SENTINEL_) { 1253ffe3c632Sopenharmony_ci val = msg.wrappers_[fieldNumber] = []; 1254ffe3c632Sopenharmony_ci } 1255ffe3c632Sopenharmony_ci return /** @type {!Array<!jspb.Message>} */ (val); 1256ffe3c632Sopenharmony_ci}; 1257ffe3c632Sopenharmony_ci 1258ffe3c632Sopenharmony_ci 1259ffe3c632Sopenharmony_ci/** 1260ffe3c632Sopenharmony_ci * Wraps underlying array into proto message representation if it wasn't done 1261ffe3c632Sopenharmony_ci * before. 1262ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 1263ffe3c632Sopenharmony_ci * @param {function(new:jspb.Message, ?Array)} ctor Constructor for the field. 1264ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1265ffe3c632Sopenharmony_ci * @private 1266ffe3c632Sopenharmony_ci */ 1267ffe3c632Sopenharmony_cijspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) { 1268ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 1269ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 1270ffe3c632Sopenharmony_ci } 1271ffe3c632Sopenharmony_ci if (!msg.wrappers_[fieldNumber]) { 1272ffe3c632Sopenharmony_ci var data = jspb.Message.getRepeatedField(msg, fieldNumber); 1273ffe3c632Sopenharmony_ci for (var wrappers = [], i = 0; i < data.length; i++) { 1274ffe3c632Sopenharmony_ci wrappers[i] = new ctor(data[i]); 1275ffe3c632Sopenharmony_ci } 1276ffe3c632Sopenharmony_ci msg.wrappers_[fieldNumber] = wrappers; 1277ffe3c632Sopenharmony_ci } 1278ffe3c632Sopenharmony_ci}; 1279ffe3c632Sopenharmony_ci 1280ffe3c632Sopenharmony_ci 1281ffe3c632Sopenharmony_ci/** 1282ffe3c632Sopenharmony_ci * Sets a proto field and syncs it to the backing array. 1283ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1284ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1285ffe3c632Sopenharmony_ci * @param {?jspb.Message|?jspb.Map|undefined} value A new value for this proto 1286ffe3c632Sopenharmony_ci * field. 1287ffe3c632Sopenharmony_ci * @return {T} the msg 1288ffe3c632Sopenharmony_ci * @template T 1289ffe3c632Sopenharmony_ci * @protected 1290ffe3c632Sopenharmony_ci */ 1291ffe3c632Sopenharmony_cijspb.Message.setWrapperField = function(msg, fieldNumber, value) { 1292ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1293ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1294ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 1295ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 1296ffe3c632Sopenharmony_ci } 1297ffe3c632Sopenharmony_ci var data = value ? value.toArray() : value; 1298ffe3c632Sopenharmony_ci msg.wrappers_[fieldNumber] = value; 1299ffe3c632Sopenharmony_ci return jspb.Message.setField(msg, fieldNumber, data); 1300ffe3c632Sopenharmony_ci}; 1301ffe3c632Sopenharmony_ci 1302ffe3c632Sopenharmony_ci 1303ffe3c632Sopenharmony_ci 1304ffe3c632Sopenharmony_ci/** 1305ffe3c632Sopenharmony_ci * Sets a proto field in a oneof union and syncs it to the backing array. 1306ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1307ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1308ffe3c632Sopenharmony_ci * @param {!Array<number>} oneof The fields belonging to the union. 1309ffe3c632Sopenharmony_ci * @param {jspb.Message|undefined} value A new value for this proto field. 1310ffe3c632Sopenharmony_ci * @return {T} the msg 1311ffe3c632Sopenharmony_ci * @template T 1312ffe3c632Sopenharmony_ci * @protected 1313ffe3c632Sopenharmony_ci */ 1314ffe3c632Sopenharmony_cijspb.Message.setOneofWrapperField = function(msg, fieldNumber, oneof, value) { 1315ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1316ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1317ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 1318ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 1319ffe3c632Sopenharmony_ci } 1320ffe3c632Sopenharmony_ci var data = value ? value.toArray() : value; 1321ffe3c632Sopenharmony_ci msg.wrappers_[fieldNumber] = value; 1322ffe3c632Sopenharmony_ci return jspb.Message.setOneofField(msg, fieldNumber, oneof, data); 1323ffe3c632Sopenharmony_ci}; 1324ffe3c632Sopenharmony_ci 1325ffe3c632Sopenharmony_ci 1326ffe3c632Sopenharmony_ci/** 1327ffe3c632Sopenharmony_ci * Sets a repeated proto field and syncs it to the backing array. 1328ffe3c632Sopenharmony_ci * @param {T} msg A jspb proto. 1329ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1330ffe3c632Sopenharmony_ci * @param {Array<!jspb.Message>|undefined} value An array of protos. 1331ffe3c632Sopenharmony_ci * @return {T} the msg 1332ffe3c632Sopenharmony_ci * @template T 1333ffe3c632Sopenharmony_ci * @protected 1334ffe3c632Sopenharmony_ci */ 1335ffe3c632Sopenharmony_cijspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) { 1336ffe3c632Sopenharmony_ci // TODO(b/35241823): replace this with a bounded generic when available 1337ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(msg, jspb.Message); 1338ffe3c632Sopenharmony_ci if (!msg.wrappers_) { 1339ffe3c632Sopenharmony_ci msg.wrappers_ = {}; 1340ffe3c632Sopenharmony_ci } 1341ffe3c632Sopenharmony_ci value = value || []; 1342ffe3c632Sopenharmony_ci for (var data = [], i = 0; i < value.length; i++) { 1343ffe3c632Sopenharmony_ci data[i] = value[i].toArray(); 1344ffe3c632Sopenharmony_ci } 1345ffe3c632Sopenharmony_ci msg.wrappers_[fieldNumber] = value; 1346ffe3c632Sopenharmony_ci return jspb.Message.setField(msg, fieldNumber, data); 1347ffe3c632Sopenharmony_ci}; 1348ffe3c632Sopenharmony_ci 1349ffe3c632Sopenharmony_ci 1350ffe3c632Sopenharmony_ci/** 1351ffe3c632Sopenharmony_ci * Add a message to a repeated proto field. 1352ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A jspb proto. 1353ffe3c632Sopenharmony_ci * @param {number} fieldNumber The field number. 1354ffe3c632Sopenharmony_ci * @param {T_CHILD|undefined} value Proto that will be added to the 1355ffe3c632Sopenharmony_ci * repeated field. 1356ffe3c632Sopenharmony_ci * @param {function(new:T_CHILD, ?Array=)} ctor The constructor of the 1357ffe3c632Sopenharmony_ci * message type. 1358ffe3c632Sopenharmony_ci * @param {number|undefined} index Index at which to insert the value. 1359ffe3c632Sopenharmony_ci * @return {T_CHILD_NOT_UNDEFINED} proto that was inserted to the repeated field 1360ffe3c632Sopenharmony_ci * @template MessageType 1361ffe3c632Sopenharmony_ci * Use go/closure-ttl to declare a non-undefined version of T_CHILD. Replace the 1362ffe3c632Sopenharmony_ci * undefined in blah|undefined with none. This is necessary because the compiler 1363ffe3c632Sopenharmony_ci * will infer T_CHILD to be |undefined. 1364ffe3c632Sopenharmony_ci * @template T_CHILD 1365ffe3c632Sopenharmony_ci * @template T_CHILD_NOT_UNDEFINED := 1366ffe3c632Sopenharmony_ci * cond(isUnknown(T_CHILD), unknown(), 1367ffe3c632Sopenharmony_ci * mapunion(T_CHILD, (X) => 1368ffe3c632Sopenharmony_ci * cond(eq(X, 'undefined'), none(), X))) 1369ffe3c632Sopenharmony_ci * =: 1370ffe3c632Sopenharmony_ci * @protected 1371ffe3c632Sopenharmony_ci */ 1372ffe3c632Sopenharmony_cijspb.Message.addToRepeatedWrapperField = function( 1373ffe3c632Sopenharmony_ci msg, fieldNumber, value, ctor, index) { 1374ffe3c632Sopenharmony_ci jspb.Message.wrapRepeatedField_(msg, ctor, fieldNumber); 1375ffe3c632Sopenharmony_ci var wrapperArray = msg.wrappers_[fieldNumber]; 1376ffe3c632Sopenharmony_ci if (!wrapperArray) { 1377ffe3c632Sopenharmony_ci wrapperArray = msg.wrappers_[fieldNumber] = []; 1378ffe3c632Sopenharmony_ci } 1379ffe3c632Sopenharmony_ci var insertedValue = value ? value : new ctor(); 1380ffe3c632Sopenharmony_ci var array = jspb.Message.getRepeatedField(msg, fieldNumber); 1381ffe3c632Sopenharmony_ci if (index != undefined) { 1382ffe3c632Sopenharmony_ci wrapperArray.splice(index, 0, insertedValue); 1383ffe3c632Sopenharmony_ci array.splice(index, 0, insertedValue.toArray()); 1384ffe3c632Sopenharmony_ci } else { 1385ffe3c632Sopenharmony_ci wrapperArray.push(insertedValue); 1386ffe3c632Sopenharmony_ci array.push(insertedValue.toArray()); 1387ffe3c632Sopenharmony_ci } 1388ffe3c632Sopenharmony_ci return insertedValue; 1389ffe3c632Sopenharmony_ci}; 1390ffe3c632Sopenharmony_ci 1391ffe3c632Sopenharmony_ci 1392ffe3c632Sopenharmony_ci/** 1393ffe3c632Sopenharmony_ci * Converts a JsPb repeated message field into a map. The map will contain 1394ffe3c632Sopenharmony_ci * protos unless an optional toObject function is given, in which case it will 1395ffe3c632Sopenharmony_ci * contain objects suitable for Soy rendering. 1396ffe3c632Sopenharmony_ci * @param {!Array<T>} field The repeated message field to be 1397ffe3c632Sopenharmony_ci * converted. 1398ffe3c632Sopenharmony_ci * @param {function() : string?} mapKeyGetterFn The function to get the key of 1399ffe3c632Sopenharmony_ci * the map. 1400ffe3c632Sopenharmony_ci * @param {?function(boolean=): Object| 1401ffe3c632Sopenharmony_ci * function((boolean|undefined),T): Object} opt_toObjectFn The 1402ffe3c632Sopenharmony_ci * toObject function for this field. We need to pass this for effective 1403ffe3c632Sopenharmony_ci * dead code removal. 1404ffe3c632Sopenharmony_ci * @param {boolean=} opt_includeInstance Whether to include the JSPB instance 1405ffe3c632Sopenharmony_ci * for transitional soy proto support: http://goto/soy-param-migration 1406ffe3c632Sopenharmony_ci * @return {!Object<string, Object>} A map of proto or Soy objects. 1407ffe3c632Sopenharmony_ci * @template T 1408ffe3c632Sopenharmony_ci */ 1409ffe3c632Sopenharmony_cijspb.Message.toMap = function( 1410ffe3c632Sopenharmony_ci field, mapKeyGetterFn, opt_toObjectFn, opt_includeInstance) { 1411ffe3c632Sopenharmony_ci var result = {}; 1412ffe3c632Sopenharmony_ci for (var i = 0; i < field.length; i++) { 1413ffe3c632Sopenharmony_ci result[mapKeyGetterFn.call(field[i])] = opt_toObjectFn ? 1414ffe3c632Sopenharmony_ci opt_toObjectFn.call(field[i], opt_includeInstance, 1415ffe3c632Sopenharmony_ci /** @type {!jspb.Message} */ (field[i])) : field[i]; 1416ffe3c632Sopenharmony_ci } 1417ffe3c632Sopenharmony_ci return result; 1418ffe3c632Sopenharmony_ci}; 1419ffe3c632Sopenharmony_ci 1420ffe3c632Sopenharmony_ci 1421ffe3c632Sopenharmony_ci/** 1422ffe3c632Sopenharmony_ci * Syncs all map fields' contents back to their underlying arrays. 1423ffe3c632Sopenharmony_ci * @private 1424ffe3c632Sopenharmony_ci */ 1425ffe3c632Sopenharmony_cijspb.Message.prototype.syncMapFields_ = function() { 1426ffe3c632Sopenharmony_ci // This iterates over submessage, map, and repeated fields, which is intended. 1427ffe3c632Sopenharmony_ci // Submessages can contain maps which also need to be synced. 1428ffe3c632Sopenharmony_ci // 1429ffe3c632Sopenharmony_ci // There is a lot of opportunity for optimization here. For example we could 1430ffe3c632Sopenharmony_ci // statically determine that some messages have no submessages with maps and 1431ffe3c632Sopenharmony_ci // optimize this method away for those just by generating one extra static 1432ffe3c632Sopenharmony_ci // boolean per message type. 1433ffe3c632Sopenharmony_ci if (this.wrappers_) { 1434ffe3c632Sopenharmony_ci for (var fieldNumber in this.wrappers_) { 1435ffe3c632Sopenharmony_ci var val = this.wrappers_[fieldNumber]; 1436ffe3c632Sopenharmony_ci if (Array.isArray(val)) { 1437ffe3c632Sopenharmony_ci for (var i = 0; i < val.length; i++) { 1438ffe3c632Sopenharmony_ci if (val[i]) { 1439ffe3c632Sopenharmony_ci val[i].toArray(); 1440ffe3c632Sopenharmony_ci } 1441ffe3c632Sopenharmony_ci } 1442ffe3c632Sopenharmony_ci } else { 1443ffe3c632Sopenharmony_ci // Works for submessages and maps. 1444ffe3c632Sopenharmony_ci if (val) { 1445ffe3c632Sopenharmony_ci val.toArray(); 1446ffe3c632Sopenharmony_ci } 1447ffe3c632Sopenharmony_ci } 1448ffe3c632Sopenharmony_ci } 1449ffe3c632Sopenharmony_ci } 1450ffe3c632Sopenharmony_ci}; 1451ffe3c632Sopenharmony_ci 1452ffe3c632Sopenharmony_ci 1453ffe3c632Sopenharmony_ci/** 1454ffe3c632Sopenharmony_ci * Returns the internal array of this proto. 1455ffe3c632Sopenharmony_ci * <p>Note: If you use this array to construct a second proto, the content 1456ffe3c632Sopenharmony_ci * would then be partially shared between the two protos. 1457ffe3c632Sopenharmony_ci * @return {!Array} The proto represented as an array. 1458ffe3c632Sopenharmony_ci */ 1459ffe3c632Sopenharmony_cijspb.Message.prototype.toArray = function() { 1460ffe3c632Sopenharmony_ci this.syncMapFields_(); 1461ffe3c632Sopenharmony_ci return this.array; 1462ffe3c632Sopenharmony_ci}; 1463ffe3c632Sopenharmony_ci 1464ffe3c632Sopenharmony_ci 1465ffe3c632Sopenharmony_ci 1466ffe3c632Sopenharmony_ciif (jspb.Message.GENERATE_TO_STRING) { 1467ffe3c632Sopenharmony_ci 1468ffe3c632Sopenharmony_ci/** 1469ffe3c632Sopenharmony_ci * Creates a string representation of the internal data array of this proto. 1470ffe3c632Sopenharmony_ci * <p>NOTE: This string is *not* suitable for use in server requests. 1471ffe3c632Sopenharmony_ci * @return {string} A string representation of this proto. 1472ffe3c632Sopenharmony_ci * @override 1473ffe3c632Sopenharmony_ci */ 1474ffe3c632Sopenharmony_cijspb.Message.prototype.toString = function() { 1475ffe3c632Sopenharmony_ci this.syncMapFields_(); 1476ffe3c632Sopenharmony_ci return this.array.toString(); 1477ffe3c632Sopenharmony_ci}; 1478ffe3c632Sopenharmony_ci 1479ffe3c632Sopenharmony_ci} 1480ffe3c632Sopenharmony_ci 1481ffe3c632Sopenharmony_ci/** 1482ffe3c632Sopenharmony_ci * Gets the value of the extension field from the extended object. 1483ffe3c632Sopenharmony_ci * @param {jspb.ExtensionFieldInfo<T>} fieldInfo Specifies the field to get. 1484ffe3c632Sopenharmony_ci * @return {T} The value of the field. 1485ffe3c632Sopenharmony_ci * @template T 1486ffe3c632Sopenharmony_ci */ 1487ffe3c632Sopenharmony_cijspb.Message.prototype.getExtension = function(fieldInfo) { 1488ffe3c632Sopenharmony_ci if (!this.extensionObject_) { 1489ffe3c632Sopenharmony_ci return undefined; 1490ffe3c632Sopenharmony_ci } 1491ffe3c632Sopenharmony_ci if (!this.wrappers_) { 1492ffe3c632Sopenharmony_ci this.wrappers_ = {}; 1493ffe3c632Sopenharmony_ci } 1494ffe3c632Sopenharmony_ci var fieldNumber = fieldInfo.fieldIndex; 1495ffe3c632Sopenharmony_ci if (fieldInfo.isRepeated) { 1496ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 1497ffe3c632Sopenharmony_ci if (!this.wrappers_[fieldNumber]) { 1498ffe3c632Sopenharmony_ci this.wrappers_[fieldNumber] = 1499ffe3c632Sopenharmony_ci goog.array.map(this.extensionObject_[fieldNumber] || [], 1500ffe3c632Sopenharmony_ci function(arr) { 1501ffe3c632Sopenharmony_ci return new fieldInfo.ctor(arr); 1502ffe3c632Sopenharmony_ci }); 1503ffe3c632Sopenharmony_ci } 1504ffe3c632Sopenharmony_ci return this.wrappers_[fieldNumber]; 1505ffe3c632Sopenharmony_ci } else { 1506ffe3c632Sopenharmony_ci return this.extensionObject_[fieldNumber]; 1507ffe3c632Sopenharmony_ci } 1508ffe3c632Sopenharmony_ci } else { 1509ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 1510ffe3c632Sopenharmony_ci if (!this.wrappers_[fieldNumber] && this.extensionObject_[fieldNumber]) { 1511ffe3c632Sopenharmony_ci this.wrappers_[fieldNumber] = new fieldInfo.ctor( 1512ffe3c632Sopenharmony_ci /** @type {Array|undefined} */ ( 1513ffe3c632Sopenharmony_ci this.extensionObject_[fieldNumber])); 1514ffe3c632Sopenharmony_ci } 1515ffe3c632Sopenharmony_ci return this.wrappers_[fieldNumber]; 1516ffe3c632Sopenharmony_ci } else { 1517ffe3c632Sopenharmony_ci return this.extensionObject_[fieldNumber]; 1518ffe3c632Sopenharmony_ci } 1519ffe3c632Sopenharmony_ci } 1520ffe3c632Sopenharmony_ci}; 1521ffe3c632Sopenharmony_ci 1522ffe3c632Sopenharmony_ci 1523ffe3c632Sopenharmony_ci/** 1524ffe3c632Sopenharmony_ci * Sets the value of the extension field in the extended object. 1525ffe3c632Sopenharmony_ci * @param {jspb.ExtensionFieldInfo} fieldInfo Specifies the field to set. 1526ffe3c632Sopenharmony_ci * @param {jspb.Message|string|Uint8Array|number|boolean|Array?} value The value 1527ffe3c632Sopenharmony_ci * to set. 1528ffe3c632Sopenharmony_ci * @return {THIS} For chaining 1529ffe3c632Sopenharmony_ci * @this {THIS} 1530ffe3c632Sopenharmony_ci * @template THIS 1531ffe3c632Sopenharmony_ci */ 1532ffe3c632Sopenharmony_cijspb.Message.prototype.setExtension = function(fieldInfo, value) { 1533ffe3c632Sopenharmony_ci // Cast self, since the inferred THIS is unknown inside the function body. 1534ffe3c632Sopenharmony_ci // https://github.com/google/closure-compiler/issues/1411#issuecomment-232442220 1535ffe3c632Sopenharmony_ci var self = /** @type {!jspb.Message} */ (this); 1536ffe3c632Sopenharmony_ci if (!self.wrappers_) { 1537ffe3c632Sopenharmony_ci self.wrappers_ = {}; 1538ffe3c632Sopenharmony_ci } 1539ffe3c632Sopenharmony_ci jspb.Message.maybeInitEmptyExtensionObject_(self); 1540ffe3c632Sopenharmony_ci var fieldNumber = fieldInfo.fieldIndex; 1541ffe3c632Sopenharmony_ci if (fieldInfo.isRepeated) { 1542ffe3c632Sopenharmony_ci value = value || []; 1543ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 1544ffe3c632Sopenharmony_ci self.wrappers_[fieldNumber] = value; 1545ffe3c632Sopenharmony_ci self.extensionObject_[fieldNumber] = goog.array.map( 1546ffe3c632Sopenharmony_ci /** @type {!Array<!jspb.Message>} */ (value), function(msg) { 1547ffe3c632Sopenharmony_ci return msg.toArray(); 1548ffe3c632Sopenharmony_ci }); 1549ffe3c632Sopenharmony_ci } else { 1550ffe3c632Sopenharmony_ci self.extensionObject_[fieldNumber] = value; 1551ffe3c632Sopenharmony_ci } 1552ffe3c632Sopenharmony_ci } else { 1553ffe3c632Sopenharmony_ci if (fieldInfo.isMessageType()) { 1554ffe3c632Sopenharmony_ci self.wrappers_[fieldNumber] = value; 1555ffe3c632Sopenharmony_ci self.extensionObject_[fieldNumber] = 1556ffe3c632Sopenharmony_ci value ? /** @type {!jspb.Message} */ (value).toArray() : value; 1557ffe3c632Sopenharmony_ci } else { 1558ffe3c632Sopenharmony_ci self.extensionObject_[fieldNumber] = value; 1559ffe3c632Sopenharmony_ci } 1560ffe3c632Sopenharmony_ci } 1561ffe3c632Sopenharmony_ci return self; 1562ffe3c632Sopenharmony_ci}; 1563ffe3c632Sopenharmony_ci 1564ffe3c632Sopenharmony_ci 1565ffe3c632Sopenharmony_ci/** 1566ffe3c632Sopenharmony_ci * Creates a difference object between two messages. 1567ffe3c632Sopenharmony_ci * 1568ffe3c632Sopenharmony_ci * The result will contain the top-level fields of m2 that differ from those of 1569ffe3c632Sopenharmony_ci * m1 at any level of nesting. No data is cloned, the result object will 1570ffe3c632Sopenharmony_ci * share its top-level elements with m2 (but not with m1). 1571ffe3c632Sopenharmony_ci * 1572ffe3c632Sopenharmony_ci * Note that repeated fields should not have null/undefined elements, but if 1573ffe3c632Sopenharmony_ci * they do, this operation will treat repeated fields of different length as 1574ffe3c632Sopenharmony_ci * the same if the only difference between them is due to trailing 1575ffe3c632Sopenharmony_ci * null/undefined values. 1576ffe3c632Sopenharmony_ci * 1577ffe3c632Sopenharmony_ci * @param {!jspb.Message} m1 The first message object. 1578ffe3c632Sopenharmony_ci * @param {!jspb.Message} m2 The second message object. 1579ffe3c632Sopenharmony_ci * @return {!jspb.Message} The difference returned as a proto message. 1580ffe3c632Sopenharmony_ci * Note that the returned message may be missing required fields. This is 1581ffe3c632Sopenharmony_ci * currently tolerated in Js, but would cause an error if you tried to 1582ffe3c632Sopenharmony_ci * send such a proto to the server. You can access the raw difference 1583ffe3c632Sopenharmony_ci * array with result.toArray(). 1584ffe3c632Sopenharmony_ci * @throws {Error} If the messages are responses with different types. 1585ffe3c632Sopenharmony_ci */ 1586ffe3c632Sopenharmony_cijspb.Message.difference = function(m1, m2) { 1587ffe3c632Sopenharmony_ci if (!(m1 instanceof m2.constructor)) { 1588ffe3c632Sopenharmony_ci throw new Error('Messages have different types.'); 1589ffe3c632Sopenharmony_ci } 1590ffe3c632Sopenharmony_ci var arr1 = m1.toArray(); 1591ffe3c632Sopenharmony_ci var arr2 = m2.toArray(); 1592ffe3c632Sopenharmony_ci var res = []; 1593ffe3c632Sopenharmony_ci var start = 0; 1594ffe3c632Sopenharmony_ci var length = arr1.length > arr2.length ? arr1.length : arr2.length; 1595ffe3c632Sopenharmony_ci if (m1.getJsPbMessageId()) { 1596ffe3c632Sopenharmony_ci res[0] = m1.getJsPbMessageId(); 1597ffe3c632Sopenharmony_ci start = 1; 1598ffe3c632Sopenharmony_ci } 1599ffe3c632Sopenharmony_ci for (var i = start; i < length; i++) { 1600ffe3c632Sopenharmony_ci if (!jspb.Message.compareFields(arr1[i], arr2[i])) { 1601ffe3c632Sopenharmony_ci res[i] = arr2[i]; 1602ffe3c632Sopenharmony_ci } 1603ffe3c632Sopenharmony_ci } 1604ffe3c632Sopenharmony_ci return new m1.constructor(res); 1605ffe3c632Sopenharmony_ci}; 1606ffe3c632Sopenharmony_ci 1607ffe3c632Sopenharmony_ci 1608ffe3c632Sopenharmony_ci/** 1609ffe3c632Sopenharmony_ci * Tests whether two messages are equal. 1610ffe3c632Sopenharmony_ci * @param {jspb.Message|undefined} m1 The first message object. 1611ffe3c632Sopenharmony_ci * @param {jspb.Message|undefined} m2 The second message object. 1612ffe3c632Sopenharmony_ci * @return {boolean} true if both messages are null/undefined, or if both are 1613ffe3c632Sopenharmony_ci * of the same type and have the same field values. 1614ffe3c632Sopenharmony_ci */ 1615ffe3c632Sopenharmony_cijspb.Message.equals = function(m1, m2) { 1616ffe3c632Sopenharmony_ci return m1 == m2 || (!!(m1 && m2) && (m1 instanceof m2.constructor) && 1617ffe3c632Sopenharmony_ci jspb.Message.compareFields(m1.toArray(), m2.toArray())); 1618ffe3c632Sopenharmony_ci}; 1619ffe3c632Sopenharmony_ci 1620ffe3c632Sopenharmony_ci 1621ffe3c632Sopenharmony_ci/** 1622ffe3c632Sopenharmony_ci * Compares two message extension fields recursively. 1623ffe3c632Sopenharmony_ci * @param {!Object} extension1 The first field. 1624ffe3c632Sopenharmony_ci * @param {!Object} extension2 The second field. 1625ffe3c632Sopenharmony_ci * @return {boolean} true if the extensions are null/undefined, or otherwise 1626ffe3c632Sopenharmony_ci * equal. 1627ffe3c632Sopenharmony_ci */ 1628ffe3c632Sopenharmony_cijspb.Message.compareExtensions = function(extension1, extension2) { 1629ffe3c632Sopenharmony_ci extension1 = extension1 || {}; 1630ffe3c632Sopenharmony_ci extension2 = extension2 || {}; 1631ffe3c632Sopenharmony_ci 1632ffe3c632Sopenharmony_ci var keys = {}; 1633ffe3c632Sopenharmony_ci for (var name in extension1) { 1634ffe3c632Sopenharmony_ci keys[name] = 0; 1635ffe3c632Sopenharmony_ci } 1636ffe3c632Sopenharmony_ci for (var name in extension2) { 1637ffe3c632Sopenharmony_ci keys[name] = 0; 1638ffe3c632Sopenharmony_ci } 1639ffe3c632Sopenharmony_ci for (name in keys) { 1640ffe3c632Sopenharmony_ci if (!jspb.Message.compareFields(extension1[name], extension2[name])) { 1641ffe3c632Sopenharmony_ci return false; 1642ffe3c632Sopenharmony_ci } 1643ffe3c632Sopenharmony_ci } 1644ffe3c632Sopenharmony_ci return true; 1645ffe3c632Sopenharmony_ci}; 1646ffe3c632Sopenharmony_ci 1647ffe3c632Sopenharmony_ci 1648ffe3c632Sopenharmony_ci/** 1649ffe3c632Sopenharmony_ci * Compares two message fields recursively. 1650ffe3c632Sopenharmony_ci * @param {*} field1 The first field. 1651ffe3c632Sopenharmony_ci * @param {*} field2 The second field. 1652ffe3c632Sopenharmony_ci * @return {boolean} true if the fields are null/undefined, or otherwise equal. 1653ffe3c632Sopenharmony_ci */ 1654ffe3c632Sopenharmony_cijspb.Message.compareFields = function(field1, field2) { 1655ffe3c632Sopenharmony_ci // If the fields are trivially equal, they're equal. 1656ffe3c632Sopenharmony_ci if (field1 == field2) return true; 1657ffe3c632Sopenharmony_ci 1658ffe3c632Sopenharmony_ci if (!goog.isObject(field1) || !goog.isObject(field2)) { 1659ffe3c632Sopenharmony_ci // NaN != NaN so we cover this case. 1660ffe3c632Sopenharmony_ci if ((typeof field1 === 'number' && isNaN(field1)) || 1661ffe3c632Sopenharmony_ci (typeof field2 === 'number' && isNaN(field2))) { 1662ffe3c632Sopenharmony_ci // One of the fields might be a string 'NaN'. 1663ffe3c632Sopenharmony_ci return String(field1) == String(field2); 1664ffe3c632Sopenharmony_ci } 1665ffe3c632Sopenharmony_ci // If the fields aren't trivially equal and one of them isn't an object, 1666ffe3c632Sopenharmony_ci // they can't possibly be equal. 1667ffe3c632Sopenharmony_ci return false; 1668ffe3c632Sopenharmony_ci } 1669ffe3c632Sopenharmony_ci 1670ffe3c632Sopenharmony_ci // We have two objects. If they're different types, they're not equal. 1671ffe3c632Sopenharmony_ci field1 = /** @type {!Object} */(field1); 1672ffe3c632Sopenharmony_ci field2 = /** @type {!Object} */(field2); 1673ffe3c632Sopenharmony_ci if (field1.constructor != field2.constructor) return false; 1674ffe3c632Sopenharmony_ci 1675ffe3c632Sopenharmony_ci // If both are Uint8Arrays, compare them element-by-element. 1676ffe3c632Sopenharmony_ci if (jspb.Message.SUPPORTS_UINT8ARRAY_ && field1.constructor === Uint8Array) { 1677ffe3c632Sopenharmony_ci var bytes1 = /** @type {!Uint8Array} */(field1); 1678ffe3c632Sopenharmony_ci var bytes2 = /** @type {!Uint8Array} */(field2); 1679ffe3c632Sopenharmony_ci if (bytes1.length != bytes2.length) return false; 1680ffe3c632Sopenharmony_ci for (var i = 0; i < bytes1.length; i++) { 1681ffe3c632Sopenharmony_ci if (bytes1[i] != bytes2[i]) return false; 1682ffe3c632Sopenharmony_ci } 1683ffe3c632Sopenharmony_ci return true; 1684ffe3c632Sopenharmony_ci } 1685ffe3c632Sopenharmony_ci 1686ffe3c632Sopenharmony_ci // If they're both Arrays, compare them element by element except for the 1687ffe3c632Sopenharmony_ci // optional extension objects at the end, which we compare separately. 1688ffe3c632Sopenharmony_ci if (field1.constructor === Array) { 1689ffe3c632Sopenharmony_ci var typedField1 = /** @type {!Array<?>} */ (field1); 1690ffe3c632Sopenharmony_ci var typedField2 = /** @type {!Array<?>} */ (field2); 1691ffe3c632Sopenharmony_ci var extension1 = undefined; 1692ffe3c632Sopenharmony_ci var extension2 = undefined; 1693ffe3c632Sopenharmony_ci 1694ffe3c632Sopenharmony_ci var length = Math.max(typedField1.length, typedField2.length); 1695ffe3c632Sopenharmony_ci for (var i = 0; i < length; i++) { 1696ffe3c632Sopenharmony_ci var val1 = typedField1[i]; 1697ffe3c632Sopenharmony_ci var val2 = typedField2[i]; 1698ffe3c632Sopenharmony_ci 1699ffe3c632Sopenharmony_ci if (val1 && (val1.constructor == Object)) { 1700ffe3c632Sopenharmony_ci goog.asserts.assert(extension1 === undefined); 1701ffe3c632Sopenharmony_ci goog.asserts.assert(i === typedField1.length - 1); 1702ffe3c632Sopenharmony_ci extension1 = val1; 1703ffe3c632Sopenharmony_ci val1 = undefined; 1704ffe3c632Sopenharmony_ci } 1705ffe3c632Sopenharmony_ci 1706ffe3c632Sopenharmony_ci if (val2 && (val2.constructor == Object)) { 1707ffe3c632Sopenharmony_ci goog.asserts.assert(extension2 === undefined); 1708ffe3c632Sopenharmony_ci goog.asserts.assert(i === typedField2.length - 1); 1709ffe3c632Sopenharmony_ci extension2 = val2; 1710ffe3c632Sopenharmony_ci val2 = undefined; 1711ffe3c632Sopenharmony_ci } 1712ffe3c632Sopenharmony_ci 1713ffe3c632Sopenharmony_ci if (!jspb.Message.compareFields(val1, val2)) { 1714ffe3c632Sopenharmony_ci return false; 1715ffe3c632Sopenharmony_ci } 1716ffe3c632Sopenharmony_ci } 1717ffe3c632Sopenharmony_ci 1718ffe3c632Sopenharmony_ci if (extension1 || extension2) { 1719ffe3c632Sopenharmony_ci extension1 = extension1 || {}; 1720ffe3c632Sopenharmony_ci extension2 = extension2 || {}; 1721ffe3c632Sopenharmony_ci return jspb.Message.compareExtensions(extension1, extension2); 1722ffe3c632Sopenharmony_ci } 1723ffe3c632Sopenharmony_ci 1724ffe3c632Sopenharmony_ci return true; 1725ffe3c632Sopenharmony_ci } 1726ffe3c632Sopenharmony_ci 1727ffe3c632Sopenharmony_ci // If they're both plain Objects (i.e. extensions), compare them as 1728ffe3c632Sopenharmony_ci // extensions. 1729ffe3c632Sopenharmony_ci if (field1.constructor === Object) { 1730ffe3c632Sopenharmony_ci return jspb.Message.compareExtensions(field1, field2); 1731ffe3c632Sopenharmony_ci } 1732ffe3c632Sopenharmony_ci 1733ffe3c632Sopenharmony_ci throw new Error('Invalid type in JSPB array'); 1734ffe3c632Sopenharmony_ci}; 1735ffe3c632Sopenharmony_ci 1736ffe3c632Sopenharmony_ci 1737ffe3c632Sopenharmony_ci/** 1738ffe3c632Sopenharmony_ci * Templated, type-safe cloneMessage definition. 1739ffe3c632Sopenharmony_ci * @return {THIS} 1740ffe3c632Sopenharmony_ci * @this {THIS} 1741ffe3c632Sopenharmony_ci * @template THIS 1742ffe3c632Sopenharmony_ci */ 1743ffe3c632Sopenharmony_cijspb.Message.prototype.cloneMessage = function() { 1744ffe3c632Sopenharmony_ci return jspb.Message.cloneMessage(/** @type {!jspb.Message} */ (this)); 1745ffe3c632Sopenharmony_ci}; 1746ffe3c632Sopenharmony_ci 1747ffe3c632Sopenharmony_ci/** 1748ffe3c632Sopenharmony_ci * Alias clone to cloneMessage. goog.object.unsafeClone uses clone to 1749ffe3c632Sopenharmony_ci * efficiently copy objects. Without this alias, copying jspb messages comes 1750ffe3c632Sopenharmony_ci * with a large performance penalty. 1751ffe3c632Sopenharmony_ci * @return {THIS} 1752ffe3c632Sopenharmony_ci * @this {THIS} 1753ffe3c632Sopenharmony_ci * @template THIS 1754ffe3c632Sopenharmony_ci */ 1755ffe3c632Sopenharmony_cijspb.Message.prototype.clone = function() { 1756ffe3c632Sopenharmony_ci return jspb.Message.cloneMessage(/** @type {!jspb.Message} */ (this)); 1757ffe3c632Sopenharmony_ci}; 1758ffe3c632Sopenharmony_ci 1759ffe3c632Sopenharmony_ci/** 1760ffe3c632Sopenharmony_ci * Static clone function. NOTE: A type-safe method called "cloneMessage" 1761ffe3c632Sopenharmony_ci * exists 1762ffe3c632Sopenharmony_ci * on each generated JsPb class. Do not call this function directly. 1763ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A message to clone. 1764ffe3c632Sopenharmony_ci * @return {!jspb.Message} A deep clone of the given message. 1765ffe3c632Sopenharmony_ci */ 1766ffe3c632Sopenharmony_cijspb.Message.clone = function(msg) { 1767ffe3c632Sopenharmony_ci // Although we could include the wrappers, we leave them out here. 1768ffe3c632Sopenharmony_ci return jspb.Message.cloneMessage(msg); 1769ffe3c632Sopenharmony_ci}; 1770ffe3c632Sopenharmony_ci 1771ffe3c632Sopenharmony_ci 1772ffe3c632Sopenharmony_ci/** 1773ffe3c632Sopenharmony_ci * @param {!jspb.Message} msg A message to clone. 1774ffe3c632Sopenharmony_ci * @return {!jspb.Message} A deep clone of the given message. 1775ffe3c632Sopenharmony_ci * @protected 1776ffe3c632Sopenharmony_ci */ 1777ffe3c632Sopenharmony_cijspb.Message.cloneMessage = function(msg) { 1778ffe3c632Sopenharmony_ci // Although we could include the wrappers, we leave them out here. 1779ffe3c632Sopenharmony_ci return new msg.constructor(jspb.Message.clone_(msg.toArray())); 1780ffe3c632Sopenharmony_ci}; 1781ffe3c632Sopenharmony_ci 1782ffe3c632Sopenharmony_ci 1783ffe3c632Sopenharmony_ci/** 1784ffe3c632Sopenharmony_ci * Takes 2 messages of the same type and copies the contents of the first 1785ffe3c632Sopenharmony_ci * message into the second. After this the 2 messages will equals in terms of 1786ffe3c632Sopenharmony_ci * value semantics but share no state. All data in the destination message will 1787ffe3c632Sopenharmony_ci * be overridden. 1788ffe3c632Sopenharmony_ci * 1789ffe3c632Sopenharmony_ci * @param {MESSAGE} fromMessage Message that will be copied into toMessage. 1790ffe3c632Sopenharmony_ci * @param {MESSAGE} toMessage Message which will receive a copy of fromMessage 1791ffe3c632Sopenharmony_ci * as its contents. 1792ffe3c632Sopenharmony_ci * @template MESSAGE 1793ffe3c632Sopenharmony_ci */ 1794ffe3c632Sopenharmony_cijspb.Message.copyInto = function(fromMessage, toMessage) { 1795ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(fromMessage, jspb.Message); 1796ffe3c632Sopenharmony_ci goog.asserts.assertInstanceof(toMessage, jspb.Message); 1797ffe3c632Sopenharmony_ci goog.asserts.assert(fromMessage.constructor == toMessage.constructor, 1798ffe3c632Sopenharmony_ci 'Copy source and target message should have the same type.'); 1799ffe3c632Sopenharmony_ci var copyOfFrom = jspb.Message.clone(fromMessage); 1800ffe3c632Sopenharmony_ci 1801ffe3c632Sopenharmony_ci var to = toMessage.toArray(); 1802ffe3c632Sopenharmony_ci var from = copyOfFrom.toArray(); 1803ffe3c632Sopenharmony_ci 1804ffe3c632Sopenharmony_ci // Empty destination in case it has more values at the end of the array. 1805ffe3c632Sopenharmony_ci to.length = 0; 1806ffe3c632Sopenharmony_ci // and then copy everything from the new to the existing message. 1807ffe3c632Sopenharmony_ci for (var i = 0; i < from.length; i++) { 1808ffe3c632Sopenharmony_ci to[i] = from[i]; 1809ffe3c632Sopenharmony_ci } 1810ffe3c632Sopenharmony_ci 1811ffe3c632Sopenharmony_ci // This is either null or empty for a fresh copy. 1812ffe3c632Sopenharmony_ci toMessage.wrappers_ = copyOfFrom.wrappers_; 1813ffe3c632Sopenharmony_ci // Just a reference into the shared array. 1814ffe3c632Sopenharmony_ci toMessage.extensionObject_ = copyOfFrom.extensionObject_; 1815ffe3c632Sopenharmony_ci}; 1816ffe3c632Sopenharmony_ci 1817ffe3c632Sopenharmony_ci 1818ffe3c632Sopenharmony_ci/** 1819ffe3c632Sopenharmony_ci * Helper for cloning an internal JsPb object. 1820ffe3c632Sopenharmony_ci * @param {!Object} obj A JsPb object, eg, a field, to be cloned. 1821ffe3c632Sopenharmony_ci * @return {!Object} A clone of the input object. 1822ffe3c632Sopenharmony_ci * @private 1823ffe3c632Sopenharmony_ci */ 1824ffe3c632Sopenharmony_cijspb.Message.clone_ = function(obj) { 1825ffe3c632Sopenharmony_ci var o; 1826ffe3c632Sopenharmony_ci if (Array.isArray(obj)) { 1827ffe3c632Sopenharmony_ci // Allocate array of correct size. 1828ffe3c632Sopenharmony_ci var clonedArray = new Array(obj.length); 1829ffe3c632Sopenharmony_ci // Use array iteration where possible because it is faster than for-in. 1830ffe3c632Sopenharmony_ci for (var i = 0; i < obj.length; i++) { 1831ffe3c632Sopenharmony_ci o = obj[i]; 1832ffe3c632Sopenharmony_ci if (o != null) { 1833ffe3c632Sopenharmony_ci // NOTE:redundant null check existing for NTI compatibility. 1834ffe3c632Sopenharmony_ci // see b/70515949 1835ffe3c632Sopenharmony_ci clonedArray[i] = (typeof o == 'object') ? 1836ffe3c632Sopenharmony_ci jspb.Message.clone_(goog.asserts.assert(o)) : 1837ffe3c632Sopenharmony_ci o; 1838ffe3c632Sopenharmony_ci } 1839ffe3c632Sopenharmony_ci } 1840ffe3c632Sopenharmony_ci return clonedArray; 1841ffe3c632Sopenharmony_ci } 1842ffe3c632Sopenharmony_ci if (jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array) { 1843ffe3c632Sopenharmony_ci return new Uint8Array(obj); 1844ffe3c632Sopenharmony_ci } 1845ffe3c632Sopenharmony_ci var clone = {}; 1846ffe3c632Sopenharmony_ci for (var key in obj) { 1847ffe3c632Sopenharmony_ci o = obj[key]; 1848ffe3c632Sopenharmony_ci if (o != null) { 1849ffe3c632Sopenharmony_ci // NOTE:redundant null check existing for NTI compatibility. 1850ffe3c632Sopenharmony_ci // see b/70515949 1851ffe3c632Sopenharmony_ci clone[key] = (typeof o == 'object') ? 1852ffe3c632Sopenharmony_ci jspb.Message.clone_(goog.asserts.assert(o)) : 1853ffe3c632Sopenharmony_ci o; 1854ffe3c632Sopenharmony_ci } 1855ffe3c632Sopenharmony_ci } 1856ffe3c632Sopenharmony_ci return clone; 1857ffe3c632Sopenharmony_ci}; 1858ffe3c632Sopenharmony_ci 1859ffe3c632Sopenharmony_ci 1860ffe3c632Sopenharmony_ci/** 1861ffe3c632Sopenharmony_ci * Registers a JsPb message type id with its constructor. 1862ffe3c632Sopenharmony_ci * @param {string} id The id for this type of message. 1863ffe3c632Sopenharmony_ci * @param {Function} constructor The message constructor. 1864ffe3c632Sopenharmony_ci */ 1865ffe3c632Sopenharmony_cijspb.Message.registerMessageType = function(id, constructor) { 1866ffe3c632Sopenharmony_ci // This is needed so we can later access messageId directly on the constructor, 1867ffe3c632Sopenharmony_ci // otherwise it is not available due to 'property collapsing' by the compiler. 1868ffe3c632Sopenharmony_ci /** 1869ffe3c632Sopenharmony_ci * @suppress {strictMissingProperties} messageId is not defined on Function 1870ffe3c632Sopenharmony_ci */ 1871ffe3c632Sopenharmony_ci constructor.messageId = id; 1872ffe3c632Sopenharmony_ci}; 1873ffe3c632Sopenharmony_ci/** 1874ffe3c632Sopenharmony_ci * The extensions registered on MessageSet. This is a map of extension 1875ffe3c632Sopenharmony_ci * field number to field info object. This should be considered as a 1876ffe3c632Sopenharmony_ci * private API. 1877ffe3c632Sopenharmony_ci * 1878ffe3c632Sopenharmony_ci * This is similar to [jspb class name].extensions object for 1879ffe3c632Sopenharmony_ci * non-MessageSet. We special case MessageSet so that we do not need 1880ffe3c632Sopenharmony_ci * to goog.require MessageSet from classes that extends MessageSet. 1881ffe3c632Sopenharmony_ci * 1882ffe3c632Sopenharmony_ci * @type {!Object<number, jspb.ExtensionFieldInfo>} 1883ffe3c632Sopenharmony_ci */ 1884ffe3c632Sopenharmony_cijspb.Message.messageSetExtensions = {}; 1885ffe3c632Sopenharmony_ci 1886ffe3c632Sopenharmony_ci/** 1887ffe3c632Sopenharmony_ci * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>} 1888ffe3c632Sopenharmony_ci */ 1889ffe3c632Sopenharmony_cijspb.Message.messageSetExtensionsBinary = {}; 1890