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_cigoog.provide('jspb.Map'); 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_cigoog.require('goog.asserts'); 34ffe3c632Sopenharmony_ci 35ffe3c632Sopenharmony_cigoog.requireType('jspb.BinaryReader'); 36ffe3c632Sopenharmony_cigoog.requireType('jspb.BinaryWriter'); 37ffe3c632Sopenharmony_ci 38ffe3c632Sopenharmony_ci 39ffe3c632Sopenharmony_ci 40ffe3c632Sopenharmony_ci/** 41ffe3c632Sopenharmony_ci * Constructs a new Map. A Map is a container that is used to implement map 42ffe3c632Sopenharmony_ci * fields on message objects. It closely follows the ES6 Map API; however, 43ffe3c632Sopenharmony_ci * it is distinct because we do not want to depend on external polyfills or 44ffe3c632Sopenharmony_ci * on ES6 itself. 45ffe3c632Sopenharmony_ci * 46ffe3c632Sopenharmony_ci * This constructor should only be called from generated message code. It is not 47ffe3c632Sopenharmony_ci * intended for general use by library consumers. 48ffe3c632Sopenharmony_ci * 49ffe3c632Sopenharmony_ci * @template K, V 50ffe3c632Sopenharmony_ci * 51ffe3c632Sopenharmony_ci * @param {!Array<!Array<?>>} arr 52ffe3c632Sopenharmony_ci * 53ffe3c632Sopenharmony_ci * @param {?function(new:V, ?=)=} opt_valueCtor 54ffe3c632Sopenharmony_ci * The constructor for type V, if type V is a message type. 55ffe3c632Sopenharmony_ci * 56ffe3c632Sopenharmony_ci * @constructor 57ffe3c632Sopenharmony_ci * @struct 58ffe3c632Sopenharmony_ci */ 59ffe3c632Sopenharmony_cijspb.Map = function(arr, opt_valueCtor) { 60ffe3c632Sopenharmony_ci /** @const @private */ 61ffe3c632Sopenharmony_ci this.arr_ = arr; 62ffe3c632Sopenharmony_ci /** @const @private */ 63ffe3c632Sopenharmony_ci this.valueCtor_ = opt_valueCtor; 64ffe3c632Sopenharmony_ci 65ffe3c632Sopenharmony_ci /** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */ 66ffe3c632Sopenharmony_ci this.map_ = {}; 67ffe3c632Sopenharmony_ci 68ffe3c632Sopenharmony_ci /** 69ffe3c632Sopenharmony_ci * Is `this.arr_ updated with respect to `this.map_`? 70ffe3c632Sopenharmony_ci * @type {boolean} 71ffe3c632Sopenharmony_ci */ 72ffe3c632Sopenharmony_ci this.arrClean = true; 73ffe3c632Sopenharmony_ci 74ffe3c632Sopenharmony_ci if (this.arr_.length > 0) { 75ffe3c632Sopenharmony_ci this.loadFromArray_(); 76ffe3c632Sopenharmony_ci } 77ffe3c632Sopenharmony_ci}; 78ffe3c632Sopenharmony_ci 79ffe3c632Sopenharmony_ci 80ffe3c632Sopenharmony_ci/** 81ffe3c632Sopenharmony_ci * Load initial content from underlying array. 82ffe3c632Sopenharmony_ci * @private 83ffe3c632Sopenharmony_ci */ 84ffe3c632Sopenharmony_cijspb.Map.prototype.loadFromArray_ = function() { 85ffe3c632Sopenharmony_ci for (var i = 0; i < this.arr_.length; i++) { 86ffe3c632Sopenharmony_ci var record = this.arr_[i]; 87ffe3c632Sopenharmony_ci var key = record[0]; 88ffe3c632Sopenharmony_ci var value = record[1]; 89ffe3c632Sopenharmony_ci this.map_[key.toString()] = new jspb.Map.Entry_(key, value); 90ffe3c632Sopenharmony_ci } 91ffe3c632Sopenharmony_ci this.arrClean = true; 92ffe3c632Sopenharmony_ci}; 93ffe3c632Sopenharmony_ci 94ffe3c632Sopenharmony_ci 95ffe3c632Sopenharmony_ci/** 96ffe3c632Sopenharmony_ci * Synchronize content to underlying array, if needed, and return it. 97ffe3c632Sopenharmony_ci * @return {!Array<!Array<!Object>>} 98ffe3c632Sopenharmony_ci */ 99ffe3c632Sopenharmony_cijspb.Map.prototype.toArray = function() { 100ffe3c632Sopenharmony_ci if (this.arrClean) { 101ffe3c632Sopenharmony_ci if (this.valueCtor_) { 102ffe3c632Sopenharmony_ci // We need to recursively sync maps in submessages to their arrays. 103ffe3c632Sopenharmony_ci var m = this.map_; 104ffe3c632Sopenharmony_ci for (var p in m) { 105ffe3c632Sopenharmony_ci if (Object.prototype.hasOwnProperty.call(m, p)) { 106ffe3c632Sopenharmony_ci var valueWrapper = /** @type {?jspb.Message} */ (m[p].valueWrapper); 107ffe3c632Sopenharmony_ci if (valueWrapper) { 108ffe3c632Sopenharmony_ci valueWrapper.toArray(); 109ffe3c632Sopenharmony_ci } 110ffe3c632Sopenharmony_ci } 111ffe3c632Sopenharmony_ci } 112ffe3c632Sopenharmony_ci } 113ffe3c632Sopenharmony_ci } else { 114ffe3c632Sopenharmony_ci // Delete all elements. 115ffe3c632Sopenharmony_ci this.arr_.length = 0; 116ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 117ffe3c632Sopenharmony_ci // Output keys in deterministic (sorted) order. 118ffe3c632Sopenharmony_ci strKeys.sort(); 119ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 120ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 121ffe3c632Sopenharmony_ci var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper); 122ffe3c632Sopenharmony_ci if (valueWrapper) { 123ffe3c632Sopenharmony_ci valueWrapper.toArray(); 124ffe3c632Sopenharmony_ci } 125ffe3c632Sopenharmony_ci this.arr_.push([entry.key, entry.value]); 126ffe3c632Sopenharmony_ci } 127ffe3c632Sopenharmony_ci this.arrClean = true; 128ffe3c632Sopenharmony_ci } 129ffe3c632Sopenharmony_ci return this.arr_; 130ffe3c632Sopenharmony_ci}; 131ffe3c632Sopenharmony_ci 132ffe3c632Sopenharmony_ci 133ffe3c632Sopenharmony_ci/** 134ffe3c632Sopenharmony_ci * Returns the map formatted as an array of key-value pairs, suitable for the 135ffe3c632Sopenharmony_ci * toObject() form of a message. 136ffe3c632Sopenharmony_ci * 137ffe3c632Sopenharmony_ci * @param {boolean=} includeInstance Whether to include the JSPB instance for 138ffe3c632Sopenharmony_ci * transitional soy proto support: http://goto/soy-param-migration 139ffe3c632Sopenharmony_ci * @param {function((boolean|undefined),V):!Object=} valueToObject 140ffe3c632Sopenharmony_ci * The static toObject() method, if V is a message type. 141ffe3c632Sopenharmony_ci * @return {!Array<!Array<!Object>>} 142ffe3c632Sopenharmony_ci */ 143ffe3c632Sopenharmony_cijspb.Map.prototype.toObject = function(includeInstance, valueToObject) { 144ffe3c632Sopenharmony_ci var rawArray = this.toArray(); 145ffe3c632Sopenharmony_ci var entries = []; 146ffe3c632Sopenharmony_ci for (var i = 0; i < rawArray.length; i++) { 147ffe3c632Sopenharmony_ci var entry = this.map_[rawArray[i][0].toString()]; 148ffe3c632Sopenharmony_ci this.wrapEntry_(entry); 149ffe3c632Sopenharmony_ci var valueWrapper = /** @type {V|undefined} */ (entry.valueWrapper); 150ffe3c632Sopenharmony_ci if (valueWrapper) { 151ffe3c632Sopenharmony_ci goog.asserts.assert(valueToObject); 152ffe3c632Sopenharmony_ci entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]); 153ffe3c632Sopenharmony_ci } else { 154ffe3c632Sopenharmony_ci entries.push([entry.key, entry.value]); 155ffe3c632Sopenharmony_ci } 156ffe3c632Sopenharmony_ci } 157ffe3c632Sopenharmony_ci return entries; 158ffe3c632Sopenharmony_ci}; 159ffe3c632Sopenharmony_ci 160ffe3c632Sopenharmony_ci 161ffe3c632Sopenharmony_ci/** 162ffe3c632Sopenharmony_ci * Returns a Map from the given array of key-value pairs when the values are of 163ffe3c632Sopenharmony_ci * message type. The values in the array must match the format returned by their 164ffe3c632Sopenharmony_ci * message type's toObject() method. 165ffe3c632Sopenharmony_ci * 166ffe3c632Sopenharmony_ci * @template K, V 167ffe3c632Sopenharmony_ci * @param {!Array<!Array<!Object>>} entries 168ffe3c632Sopenharmony_ci * @param {function(new:V,?=)} valueCtor 169ffe3c632Sopenharmony_ci * The constructor for type V. 170ffe3c632Sopenharmony_ci * @param {function(!Object):V} valueFromObject 171ffe3c632Sopenharmony_ci * The fromObject function for type V. 172ffe3c632Sopenharmony_ci * @return {!jspb.Map<K, V>} 173ffe3c632Sopenharmony_ci */ 174ffe3c632Sopenharmony_cijspb.Map.fromObject = function(entries, valueCtor, valueFromObject) { 175ffe3c632Sopenharmony_ci var result = new jspb.Map([], valueCtor); 176ffe3c632Sopenharmony_ci for (var i = 0; i < entries.length; i++) { 177ffe3c632Sopenharmony_ci var key = entries[i][0]; 178ffe3c632Sopenharmony_ci var value = valueFromObject(entries[i][1]); 179ffe3c632Sopenharmony_ci result.set(key, value); 180ffe3c632Sopenharmony_ci } 181ffe3c632Sopenharmony_ci return result; 182ffe3c632Sopenharmony_ci}; 183ffe3c632Sopenharmony_ci 184ffe3c632Sopenharmony_ci 185ffe3c632Sopenharmony_ci/** 186ffe3c632Sopenharmony_ci * Helper: an IteratorIterable over an array. 187ffe3c632Sopenharmony_ci * @template T 188ffe3c632Sopenharmony_ci * @param {!Array<T>} arr the array 189ffe3c632Sopenharmony_ci * @implements {IteratorIterable<T>} 190ffe3c632Sopenharmony_ci * @constructor @struct 191ffe3c632Sopenharmony_ci * @private 192ffe3c632Sopenharmony_ci */ 193ffe3c632Sopenharmony_cijspb.Map.ArrayIteratorIterable_ = function(arr) { 194ffe3c632Sopenharmony_ci /** @type {number} @private */ 195ffe3c632Sopenharmony_ci this.idx_ = 0; 196ffe3c632Sopenharmony_ci 197ffe3c632Sopenharmony_ci /** @const @private */ 198ffe3c632Sopenharmony_ci this.arr_ = arr; 199ffe3c632Sopenharmony_ci}; 200ffe3c632Sopenharmony_ci 201ffe3c632Sopenharmony_ci 202ffe3c632Sopenharmony_ci/** @override @final */ 203ffe3c632Sopenharmony_cijspb.Map.ArrayIteratorIterable_.prototype.next = function() { 204ffe3c632Sopenharmony_ci if (this.idx_ < this.arr_.length) { 205ffe3c632Sopenharmony_ci return {done: false, value: this.arr_[this.idx_++]}; 206ffe3c632Sopenharmony_ci } else { 207ffe3c632Sopenharmony_ci return {done: true, value: undefined}; 208ffe3c632Sopenharmony_ci } 209ffe3c632Sopenharmony_ci}; 210ffe3c632Sopenharmony_ci 211ffe3c632Sopenharmony_ciif (typeof(Symbol) != 'undefined') { 212ffe3c632Sopenharmony_ci /** @override */ 213ffe3c632Sopenharmony_ci jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] = function() { 214ffe3c632Sopenharmony_ci return this; 215ffe3c632Sopenharmony_ci }; 216ffe3c632Sopenharmony_ci} 217ffe3c632Sopenharmony_ci 218ffe3c632Sopenharmony_ci 219ffe3c632Sopenharmony_ci/** 220ffe3c632Sopenharmony_ci * Returns the map's length (number of key/value pairs). 221ffe3c632Sopenharmony_ci * @return {number} 222ffe3c632Sopenharmony_ci */ 223ffe3c632Sopenharmony_cijspb.Map.prototype.getLength = function() { 224ffe3c632Sopenharmony_ci return this.stringKeys_().length; 225ffe3c632Sopenharmony_ci}; 226ffe3c632Sopenharmony_ci 227ffe3c632Sopenharmony_ci 228ffe3c632Sopenharmony_ci/** 229ffe3c632Sopenharmony_ci * Clears the map. 230ffe3c632Sopenharmony_ci */ 231ffe3c632Sopenharmony_cijspb.Map.prototype.clear = function() { 232ffe3c632Sopenharmony_ci this.map_ = {}; 233ffe3c632Sopenharmony_ci this.arrClean = false; 234ffe3c632Sopenharmony_ci}; 235ffe3c632Sopenharmony_ci 236ffe3c632Sopenharmony_ci 237ffe3c632Sopenharmony_ci/** 238ffe3c632Sopenharmony_ci * Deletes a particular key from the map. 239ffe3c632Sopenharmony_ci * N.B.: differs in name from ES6 Map's `delete` because IE8 does not support 240ffe3c632Sopenharmony_ci * reserved words as property names. 241ffe3c632Sopenharmony_ci * @this {jspb.Map} 242ffe3c632Sopenharmony_ci * @param {K} key 243ffe3c632Sopenharmony_ci * @return {boolean} Whether any entry with this key was deleted. 244ffe3c632Sopenharmony_ci */ 245ffe3c632Sopenharmony_cijspb.Map.prototype.del = function(key) { 246ffe3c632Sopenharmony_ci var keyValue = key.toString(); 247ffe3c632Sopenharmony_ci var hadKey = this.map_.hasOwnProperty(keyValue); 248ffe3c632Sopenharmony_ci delete this.map_[keyValue]; 249ffe3c632Sopenharmony_ci this.arrClean = false; 250ffe3c632Sopenharmony_ci return hadKey; 251ffe3c632Sopenharmony_ci}; 252ffe3c632Sopenharmony_ci 253ffe3c632Sopenharmony_ci 254ffe3c632Sopenharmony_ci/** 255ffe3c632Sopenharmony_ci * Returns an array of [key, value] pairs in the map. 256ffe3c632Sopenharmony_ci * 257ffe3c632Sopenharmony_ci * This is redundant compared to the plain entries() method, but we provide this 258ffe3c632Sopenharmony_ci * to help out Angular 1.x users. Still evaluating whether this is the best 259ffe3c632Sopenharmony_ci * option. 260ffe3c632Sopenharmony_ci * 261ffe3c632Sopenharmony_ci * @return {!Array<!Array<K|V>>} 262ffe3c632Sopenharmony_ci */ 263ffe3c632Sopenharmony_cijspb.Map.prototype.getEntryList = function() { 264ffe3c632Sopenharmony_ci var entries = []; 265ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 266ffe3c632Sopenharmony_ci strKeys.sort(); 267ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 268ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 269ffe3c632Sopenharmony_ci entries.push([entry.key, entry.value]); 270ffe3c632Sopenharmony_ci } 271ffe3c632Sopenharmony_ci return entries; 272ffe3c632Sopenharmony_ci}; 273ffe3c632Sopenharmony_ci 274ffe3c632Sopenharmony_ci 275ffe3c632Sopenharmony_ci/** 276ffe3c632Sopenharmony_ci * Returns an iterator-iterable over [key, value] pairs in the map. 277ffe3c632Sopenharmony_ci * Closure compiler sadly doesn't support tuples, ie. Iterator<[K,V]>. 278ffe3c632Sopenharmony_ci * @return {!IteratorIterable<!Array<K|V>>} The iterator-iterable. 279ffe3c632Sopenharmony_ci */ 280ffe3c632Sopenharmony_cijspb.Map.prototype.entries = function() { 281ffe3c632Sopenharmony_ci var entries = []; 282ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 283ffe3c632Sopenharmony_ci strKeys.sort(); 284ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 285ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 286ffe3c632Sopenharmony_ci entries.push([entry.key, this.wrapEntry_(entry)]); 287ffe3c632Sopenharmony_ci } 288ffe3c632Sopenharmony_ci return new jspb.Map.ArrayIteratorIterable_(entries); 289ffe3c632Sopenharmony_ci}; 290ffe3c632Sopenharmony_ci 291ffe3c632Sopenharmony_ci 292ffe3c632Sopenharmony_ci/** 293ffe3c632Sopenharmony_ci * Returns an iterator-iterable over keys in the map. 294ffe3c632Sopenharmony_ci * @return {!IteratorIterable<K>} The iterator-iterable. 295ffe3c632Sopenharmony_ci */ 296ffe3c632Sopenharmony_cijspb.Map.prototype.keys = function() { 297ffe3c632Sopenharmony_ci var keys = []; 298ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 299ffe3c632Sopenharmony_ci strKeys.sort(); 300ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 301ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 302ffe3c632Sopenharmony_ci keys.push(entry.key); 303ffe3c632Sopenharmony_ci } 304ffe3c632Sopenharmony_ci return new jspb.Map.ArrayIteratorIterable_(keys); 305ffe3c632Sopenharmony_ci}; 306ffe3c632Sopenharmony_ci 307ffe3c632Sopenharmony_ci 308ffe3c632Sopenharmony_ci/** 309ffe3c632Sopenharmony_ci * Returns an iterator-iterable over values in the map. 310ffe3c632Sopenharmony_ci * @return {!IteratorIterable<V>} The iterator-iterable. 311ffe3c632Sopenharmony_ci */ 312ffe3c632Sopenharmony_cijspb.Map.prototype.values = function() { 313ffe3c632Sopenharmony_ci var values = []; 314ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 315ffe3c632Sopenharmony_ci strKeys.sort(); 316ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 317ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 318ffe3c632Sopenharmony_ci values.push(this.wrapEntry_(entry)); 319ffe3c632Sopenharmony_ci } 320ffe3c632Sopenharmony_ci return new jspb.Map.ArrayIteratorIterable_(values); 321ffe3c632Sopenharmony_ci}; 322ffe3c632Sopenharmony_ci 323ffe3c632Sopenharmony_ci 324ffe3c632Sopenharmony_ci/** 325ffe3c632Sopenharmony_ci * Iterates over entries in the map, calling a function on each. 326ffe3c632Sopenharmony_ci * @template T 327ffe3c632Sopenharmony_ci * @param {function(this:T, V, K, ?jspb.Map<K, V>)} cb 328ffe3c632Sopenharmony_ci * @param {T=} opt_thisArg 329ffe3c632Sopenharmony_ci */ 330ffe3c632Sopenharmony_cijspb.Map.prototype.forEach = function(cb, opt_thisArg) { 331ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 332ffe3c632Sopenharmony_ci strKeys.sort(); 333ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 334ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 335ffe3c632Sopenharmony_ci cb.call(opt_thisArg, this.wrapEntry_(entry), entry.key, this); 336ffe3c632Sopenharmony_ci } 337ffe3c632Sopenharmony_ci}; 338ffe3c632Sopenharmony_ci 339ffe3c632Sopenharmony_ci 340ffe3c632Sopenharmony_ci/** 341ffe3c632Sopenharmony_ci * Sets a key in the map to the given value. 342ffe3c632Sopenharmony_ci * @param {K} key The key 343ffe3c632Sopenharmony_ci * @param {V} value The value 344ffe3c632Sopenharmony_ci * @return {!jspb.Map<K,V>} 345ffe3c632Sopenharmony_ci */ 346ffe3c632Sopenharmony_cijspb.Map.prototype.set = function(key, value) { 347ffe3c632Sopenharmony_ci var entry = new jspb.Map.Entry_(key); 348ffe3c632Sopenharmony_ci if (this.valueCtor_) { 349ffe3c632Sopenharmony_ci entry.valueWrapper = value; 350ffe3c632Sopenharmony_ci // .toArray() on a message returns a reference to the underlying array 351ffe3c632Sopenharmony_ci // rather than a copy. 352ffe3c632Sopenharmony_ci entry.value = value.toArray(); 353ffe3c632Sopenharmony_ci } else { 354ffe3c632Sopenharmony_ci entry.value = value; 355ffe3c632Sopenharmony_ci } 356ffe3c632Sopenharmony_ci this.map_[key.toString()] = entry; 357ffe3c632Sopenharmony_ci this.arrClean = false; 358ffe3c632Sopenharmony_ci return this; 359ffe3c632Sopenharmony_ci}; 360ffe3c632Sopenharmony_ci 361ffe3c632Sopenharmony_ci 362ffe3c632Sopenharmony_ci/** 363ffe3c632Sopenharmony_ci * Helper: lazily construct a wrapper around an entry, if needed, and return the 364ffe3c632Sopenharmony_ci * user-visible type. 365ffe3c632Sopenharmony_ci * @param {!jspb.Map.Entry_<K,V>} entry 366ffe3c632Sopenharmony_ci * @return {V} 367ffe3c632Sopenharmony_ci * @private 368ffe3c632Sopenharmony_ci */ 369ffe3c632Sopenharmony_cijspb.Map.prototype.wrapEntry_ = function(entry) { 370ffe3c632Sopenharmony_ci if (this.valueCtor_) { 371ffe3c632Sopenharmony_ci if (!entry.valueWrapper) { 372ffe3c632Sopenharmony_ci entry.valueWrapper = new this.valueCtor_(entry.value); 373ffe3c632Sopenharmony_ci } 374ffe3c632Sopenharmony_ci return /** @type {V} */ (entry.valueWrapper); 375ffe3c632Sopenharmony_ci } else { 376ffe3c632Sopenharmony_ci return entry.value; 377ffe3c632Sopenharmony_ci } 378ffe3c632Sopenharmony_ci}; 379ffe3c632Sopenharmony_ci 380ffe3c632Sopenharmony_ci 381ffe3c632Sopenharmony_ci/** 382ffe3c632Sopenharmony_ci * Gets the value corresponding to a key in the map. 383ffe3c632Sopenharmony_ci * @param {K} key 384ffe3c632Sopenharmony_ci * @return {V|undefined} The value, or `undefined` if key not present 385ffe3c632Sopenharmony_ci */ 386ffe3c632Sopenharmony_cijspb.Map.prototype.get = function(key) { 387ffe3c632Sopenharmony_ci var keyValue = key.toString(); 388ffe3c632Sopenharmony_ci var entry = this.map_[keyValue]; 389ffe3c632Sopenharmony_ci if (entry) { 390ffe3c632Sopenharmony_ci return this.wrapEntry_(entry); 391ffe3c632Sopenharmony_ci } else { 392ffe3c632Sopenharmony_ci return undefined; 393ffe3c632Sopenharmony_ci } 394ffe3c632Sopenharmony_ci}; 395ffe3c632Sopenharmony_ci 396ffe3c632Sopenharmony_ci 397ffe3c632Sopenharmony_ci/** 398ffe3c632Sopenharmony_ci * Determines whether the given key is present in the map. 399ffe3c632Sopenharmony_ci * @param {K} key 400ffe3c632Sopenharmony_ci * @return {boolean} `true` if the key is present 401ffe3c632Sopenharmony_ci */ 402ffe3c632Sopenharmony_cijspb.Map.prototype.has = function(key) { 403ffe3c632Sopenharmony_ci var keyValue = key.toString(); 404ffe3c632Sopenharmony_ci return (keyValue in this.map_); 405ffe3c632Sopenharmony_ci}; 406ffe3c632Sopenharmony_ci 407ffe3c632Sopenharmony_ci 408ffe3c632Sopenharmony_ci/** 409ffe3c632Sopenharmony_ci * Write this Map field in wire format to a BinaryWriter, using the given field 410ffe3c632Sopenharmony_ci * number. 411ffe3c632Sopenharmony_ci * @param {number} fieldNumber 412ffe3c632Sopenharmony_ci * @param {!jspb.BinaryWriter} writer 413ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryWriter,number,K)} keyWriterFn 414ffe3c632Sopenharmony_ci * The method on BinaryWriter that writes type K to the stream. 415ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryWriter,number,V,?=)| 416ffe3c632Sopenharmony_ci * function(this:jspb.BinaryWriter,number,V,?)} valueWriterFn 417ffe3c632Sopenharmony_ci * The method on BinaryWriter that writes type V to the stream. May be 418ffe3c632Sopenharmony_ci * writeMessage, in which case the second callback arg form is used. 419ffe3c632Sopenharmony_ci * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback 420ffe3c632Sopenharmony_ci * The BinaryWriter serialization callback for type V, if V is a message 421ffe3c632Sopenharmony_ci * type. 422ffe3c632Sopenharmony_ci */ 423ffe3c632Sopenharmony_cijspb.Map.prototype.serializeBinary = function( 424ffe3c632Sopenharmony_ci fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) { 425ffe3c632Sopenharmony_ci var strKeys = this.stringKeys_(); 426ffe3c632Sopenharmony_ci strKeys.sort(); 427ffe3c632Sopenharmony_ci for (var i = 0; i < strKeys.length; i++) { 428ffe3c632Sopenharmony_ci var entry = this.map_[strKeys[i]]; 429ffe3c632Sopenharmony_ci writer.beginSubMessage(fieldNumber); 430ffe3c632Sopenharmony_ci keyWriterFn.call(writer, 1, entry.key); 431ffe3c632Sopenharmony_ci if (this.valueCtor_) { 432ffe3c632Sopenharmony_ci valueWriterFn.call(writer, 2, this.wrapEntry_(entry), 433ffe3c632Sopenharmony_ci opt_valueWriterCallback); 434ffe3c632Sopenharmony_ci } else { 435ffe3c632Sopenharmony_ci /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn) 436ffe3c632Sopenharmony_ci .call(writer, 2, entry.value); 437ffe3c632Sopenharmony_ci } 438ffe3c632Sopenharmony_ci writer.endSubMessage(); 439ffe3c632Sopenharmony_ci } 440ffe3c632Sopenharmony_ci}; 441ffe3c632Sopenharmony_ci 442ffe3c632Sopenharmony_ci 443ffe3c632Sopenharmony_ci/** 444ffe3c632Sopenharmony_ci * Read one key/value message from the given BinaryReader. Compatible as the 445ffe3c632Sopenharmony_ci * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called 446ffe3c632Sopenharmony_ci * when a key/value pair submessage is encountered. If the Key is undefined, 447ffe3c632Sopenharmony_ci * we should default it to 0. 448ffe3c632Sopenharmony_ci * @template K, V 449ffe3c632Sopenharmony_ci * @param {!jspb.Map} map 450ffe3c632Sopenharmony_ci * @param {!jspb.BinaryReader} reader 451ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryReader):K} keyReaderFn 452ffe3c632Sopenharmony_ci * The method on BinaryReader that reads type K from the stream. 453ffe3c632Sopenharmony_ci * 454ffe3c632Sopenharmony_ci * @param {function(this:jspb.BinaryReader):V| 455ffe3c632Sopenharmony_ci * function(this:jspb.BinaryReader,V, 456ffe3c632Sopenharmony_ci * function(V,!jspb.BinaryReader))} valueReaderFn 457ffe3c632Sopenharmony_ci * The method on BinaryReader that reads type V from the stream. May be 458ffe3c632Sopenharmony_ci * readMessage, in which case the second callback arg form is used. 459ffe3c632Sopenharmony_ci * 460ffe3c632Sopenharmony_ci * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback 461ffe3c632Sopenharmony_ci * The BinaryReader parsing callback for type V, if V is a message type 462ffe3c632Sopenharmony_ci * 463ffe3c632Sopenharmony_ci * @param {K=} opt_defaultKey 464ffe3c632Sopenharmony_ci * The default value for the type of map keys. Accepting map entries with 465ffe3c632Sopenharmony_ci * unset keys is required for maps to be backwards compatible with the 466ffe3c632Sopenharmony_ci * repeated message representation described here: goo.gl/zuoLAC 467ffe3c632Sopenharmony_ci * 468ffe3c632Sopenharmony_ci * @param {V=} opt_defaultValue 469ffe3c632Sopenharmony_ci * The default value for the type of map values. Accepting map entries with 470ffe3c632Sopenharmony_ci * unset values is required for maps to be backwards compatible with the 471ffe3c632Sopenharmony_ci * repeated message representation described here: goo.gl/zuoLAC 472ffe3c632Sopenharmony_ci * 473ffe3c632Sopenharmony_ci */ 474ffe3c632Sopenharmony_cijspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn, 475ffe3c632Sopenharmony_ci opt_valueReaderCallback, opt_defaultKey, 476ffe3c632Sopenharmony_ci opt_defaultValue) { 477ffe3c632Sopenharmony_ci var key = opt_defaultKey; 478ffe3c632Sopenharmony_ci var value = opt_defaultValue; 479ffe3c632Sopenharmony_ci 480ffe3c632Sopenharmony_ci while (reader.nextField()) { 481ffe3c632Sopenharmony_ci if (reader.isEndGroup()) { 482ffe3c632Sopenharmony_ci break; 483ffe3c632Sopenharmony_ci } 484ffe3c632Sopenharmony_ci var field = reader.getFieldNumber(); 485ffe3c632Sopenharmony_ci 486ffe3c632Sopenharmony_ci if (field == 1) { 487ffe3c632Sopenharmony_ci // Key. 488ffe3c632Sopenharmony_ci key = keyReaderFn.call(reader); 489ffe3c632Sopenharmony_ci } else if (field == 2) { 490ffe3c632Sopenharmony_ci // Value. 491ffe3c632Sopenharmony_ci if (map.valueCtor_) { 492ffe3c632Sopenharmony_ci goog.asserts.assert(opt_valueReaderCallback); 493ffe3c632Sopenharmony_ci if (!value) { 494ffe3c632Sopenharmony_ci // Old generator still doesn't provide default value message. 495ffe3c632Sopenharmony_ci // Need this for backward compatibility. 496ffe3c632Sopenharmony_ci value = new map.valueCtor_(); 497ffe3c632Sopenharmony_ci } 498ffe3c632Sopenharmony_ci valueReaderFn.call(reader, value, opt_valueReaderCallback); 499ffe3c632Sopenharmony_ci } else { 500ffe3c632Sopenharmony_ci value = 501ffe3c632Sopenharmony_ci (/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn)) 502ffe3c632Sopenharmony_ci .call(reader); 503ffe3c632Sopenharmony_ci } 504ffe3c632Sopenharmony_ci } 505ffe3c632Sopenharmony_ci } 506ffe3c632Sopenharmony_ci 507ffe3c632Sopenharmony_ci goog.asserts.assert(key != undefined); 508ffe3c632Sopenharmony_ci goog.asserts.assert(value != undefined); 509ffe3c632Sopenharmony_ci map.set(key, value); 510ffe3c632Sopenharmony_ci}; 511ffe3c632Sopenharmony_ci 512ffe3c632Sopenharmony_ci 513ffe3c632Sopenharmony_ci/** 514ffe3c632Sopenharmony_ci * Helper: compute the list of all stringified keys in the underlying Object 515ffe3c632Sopenharmony_ci * map. 516ffe3c632Sopenharmony_ci * @return {!Array<string>} 517ffe3c632Sopenharmony_ci * @private 518ffe3c632Sopenharmony_ci */ 519ffe3c632Sopenharmony_cijspb.Map.prototype.stringKeys_ = function() { 520ffe3c632Sopenharmony_ci var m = this.map_; 521ffe3c632Sopenharmony_ci var ret = []; 522ffe3c632Sopenharmony_ci for (var p in m) { 523ffe3c632Sopenharmony_ci if (Object.prototype.hasOwnProperty.call(m, p)) { 524ffe3c632Sopenharmony_ci ret.push(p); 525ffe3c632Sopenharmony_ci } 526ffe3c632Sopenharmony_ci } 527ffe3c632Sopenharmony_ci return ret; 528ffe3c632Sopenharmony_ci}; 529ffe3c632Sopenharmony_ci 530ffe3c632Sopenharmony_ci 531ffe3c632Sopenharmony_ci 532ffe3c632Sopenharmony_ci/** 533ffe3c632Sopenharmony_ci * @param {K} key The entry's key. 534ffe3c632Sopenharmony_ci * @param {V=} opt_value The entry's value wrapper. 535ffe3c632Sopenharmony_ci * @constructor 536ffe3c632Sopenharmony_ci * @struct 537ffe3c632Sopenharmony_ci * @template K, V 538ffe3c632Sopenharmony_ci * @private 539ffe3c632Sopenharmony_ci */ 540ffe3c632Sopenharmony_cijspb.Map.Entry_ = function(key, opt_value) { 541ffe3c632Sopenharmony_ci /** @const {K} */ 542ffe3c632Sopenharmony_ci this.key = key; 543ffe3c632Sopenharmony_ci 544ffe3c632Sopenharmony_ci // The JSPB-serializable value. For primitive types this will be of type V. 545ffe3c632Sopenharmony_ci // For message types it will be an array. 546ffe3c632Sopenharmony_ci /** @type {V} */ 547ffe3c632Sopenharmony_ci this.value = opt_value; 548ffe3c632Sopenharmony_ci 549ffe3c632Sopenharmony_ci // Only used for submessage values. 550ffe3c632Sopenharmony_ci /** @type {V} */ 551ffe3c632Sopenharmony_ci this.valueWrapper = undefined; 552ffe3c632Sopenharmony_ci}; 553