Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(890)

Side by Side Diff: third_party/protobuf/js/map.js

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Update to new HEAD (b7632464b4) + restore GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 goog.provide('jspb.Map');
32
33 goog.require('goog.asserts');
34
35 goog.forwardDeclare('jspb.BinaryReader');
36 goog.forwardDeclare('jspb.BinaryWriter');
37
38
39
40 /**
41 * Constructs a new Map. A Map is a container that is used to implement map
42 * fields on message objects. It closely follows the ES6 Map API; however,
43 * it is distinct because we do not want to depend on external polyfills or
44 * on ES6 itself.
45 *
46 * This constructor should only be called from generated message code. It is not
47 * intended for general use by library consumers.
48 *
49 * @template K, V
50 *
51 * @param {!Array<!Array<!Object>>} arr
52 *
53 * @param {?function(new:V)|function(new:V,?)=} opt_valueCtor
54 * The constructor for type V, if type V is a message type.
55 *
56 * @constructor
57 * @struct
58 */
59 jspb.Map = function(arr, opt_valueCtor) {
60 /** @const @private */
61 this.arr_ = arr;
62 /** @const @private */
63 this.valueCtor_ = opt_valueCtor;
64
65 /** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */
66 this.map_ = {};
67
68 /**
69 * Is `this.arr_ updated with respect to `this.map_`?
70 * @type {boolean}
71 */
72 this.arrClean = true;
73
74 if (this.arr_.length > 0) {
75 this.loadFromArray_();
76 }
77 };
78
79
80 /**
81 * Load initial content from underlying array.
82 * @private
83 */
84 jspb.Map.prototype.loadFromArray_ = function() {
85 for (var i = 0; i < this.arr_.length; i++) {
86 var record = this.arr_[i];
87 var key = record[0];
88 var value = record[1];
89 this.map_[key.toString()] = new jspb.Map.Entry_(key, value);
90 }
91 this.arrClean = true;
92 };
93
94
95 /**
96 * Synchronize content to underlying array, if needed, and return it.
97 * @return {!Array<!Array<!Object>>}
98 */
99 jspb.Map.prototype.toArray = function() {
100 if (this.arrClean) {
101 if (this.valueCtor_) {
102 // We need to recursively sync maps in submessages to their arrays.
103 var m = this.map_;
104 for (var p in m) {
105 if (Object.prototype.hasOwnProperty.call(m, p)) {
106 var valueWrapper = /** @type {?jspb.Message} */ (m[p].valueWrapper);
107 if (valueWrapper) {
108 valueWrapper.toArray();
109 }
110 }
111 }
112 }
113 } else {
114 // Delete all elements.
115 this.arr_.length = 0;
116 var strKeys = this.stringKeys_();
117 // Output keys in deterministic (sorted) order.
118 strKeys.sort();
119 for (var i = 0; i < strKeys.length; i++) {
120 var entry = this.map_[strKeys[i]];
121 var valueWrapper = /** @type {!Object} */ (entry.valueWrapper);
122 if (valueWrapper) {
123 valueWrapper.toArray();
124 }
125 this.arr_.push([entry.key, entry.value]);
126 }
127 this.arrClean = true;
128 }
129 return this.arr_;
130 };
131
132
133 /**
134 * Helper: return an iterator over an array.
135 * @template T
136 * @param {!Array<T>} arr the array
137 * @return {!Iterator<T>} an iterator
138 * @private
139 */
140 jspb.Map.arrayIterator_ = function(arr) {
141 var idx = 0;
142 return /** @type {!Iterator} */ ({
143 next: function() {
144 if (idx < arr.length) {
145 return { done: false, value: arr[idx++] };
146 } else {
147 return { done: true };
148 }
149 }
150 });
151 };
152
153
154 /**
155 * Returns the map's length (number of key/value pairs).
156 * @return {number}
157 */
158 jspb.Map.prototype.getLength = function() {
159 return this.stringKeys_().length;
160 };
161
162
163 /**
164 * Clears the map.
165 */
166 jspb.Map.prototype.clear = function() {
167 this.map_ = {};
168 this.arrClean = false;
169 };
170
171
172 /**
173 * Deletes a particular key from the map.
174 * N.B.: differs in name from ES6 Map's `delete` because IE8 does not support
175 * reserved words as property names.
176 * @this {jspb.Map}
177 * @param {K} key
178 * @return {boolean} Whether any entry with this key was deleted.
179 */
180 jspb.Map.prototype.del = function(key) {
181 var keyValue = key.toString();
182 var hadKey = this.map_.hasOwnProperty(keyValue);
183 delete this.map_[keyValue];
184 this.arrClean = false;
185 return hadKey;
186 };
187
188
189 /**
190 * Returns an array of [key, value] pairs in the map.
191 *
192 * This is redundant compared to the plain entries() method, but we provide this
193 * to help out Angular 1.x users. Still evaluating whether this is the best
194 * option.
195 *
196 * @return {!Array<K|V>}
197 */
198 jspb.Map.prototype.getEntryList = function() {
199 var entries = [];
200 var strKeys = this.stringKeys_();
201 strKeys.sort();
202 for (var i = 0; i < strKeys.length; i++) {
203 var entry = this.map_[strKeys[i]];
204 entries.push([entry.key, entry.value]);
205 }
206 return entries;
207 };
208
209
210 /**
211 * Returns an iterator over [key, value] pairs in the map.
212 * Closure compiler sadly doesn't support tuples, ie. Iterator<[K,V]>.
213 * @return {!Iterator<!Array<K|V>>}
214 * The iterator
215 */
216 jspb.Map.prototype.entries = function() {
217 var entries = [];
218 var strKeys = this.stringKeys_();
219 strKeys.sort();
220 for (var i = 0; i < strKeys.length; i++) {
221 var entry = this.map_[strKeys[i]];
222 entries.push([entry.key, this.wrapEntry_(entry)]);
223 }
224 return jspb.Map.arrayIterator_(entries);
225 };
226
227
228 /**
229 * Returns an iterator over keys in the map.
230 * @return {!Iterator<K>} The iterator
231 */
232 jspb.Map.prototype.keys = function() {
233 var keys = [];
234 var strKeys = this.stringKeys_();
235 strKeys.sort();
236 for (var i = 0; i < strKeys.length; i++) {
237 var entry = this.map_[strKeys[i]];
238 keys.push(entry.key);
239 }
240 return jspb.Map.arrayIterator_(keys);
241 };
242
243
244 /**
245 * Returns an iterator over values in the map.
246 * @return {!Iterator<V>} The iterator
247 */
248 jspb.Map.prototype.values = function() {
249 var values = [];
250 var strKeys = this.stringKeys_();
251 strKeys.sort();
252 for (var i = 0; i < strKeys.length; i++) {
253 var entry = this.map_[strKeys[i]];
254 values.push(this.wrapEntry_(entry));
255 }
256 return jspb.Map.arrayIterator_(values);
257 };
258
259
260 /**
261 * Iterates over entries in the map, calling a function on each.
262 * @template T
263 * @param {function(this:T, V, K, ?jspb.Map<K, V>)} cb
264 * @param {T=} opt_thisArg
265 */
266 jspb.Map.prototype.forEach = function(cb, opt_thisArg) {
267 var strKeys = this.stringKeys_();
268 strKeys.sort();
269 for (var i = 0; i < strKeys.length; i++) {
270 var entry = this.map_[strKeys[i]];
271 cb.call(opt_thisArg, this.wrapEntry_(entry), entry.key, this);
272 }
273 };
274
275
276 /**
277 * Sets a key in the map to the given value.
278 * @param {K} key The key
279 * @param {V} value The value
280 * @return {!jspb.Map<K,V>}
281 */
282 jspb.Map.prototype.set = function(key, value) {
283 var entry = new jspb.Map.Entry_(key);
284 if (this.valueCtor_) {
285 entry.valueWrapper = value;
286 // .toArray() on a message returns a reference to the underlying array
287 // rather than a copy.
288 entry.value = value.toArray();
289 } else {
290 entry.value = value;
291 }
292 this.map_[key.toString()] = entry;
293 this.arrClean = false;
294 return this;
295 };
296
297
298 /**
299 * Helper: lazily construct a wrapper around an entry, if needed, and return the
300 * user-visible type.
301 * @param {!jspb.Map.Entry_<K,V>} entry
302 * @return {V}
303 * @private
304 */
305 jspb.Map.prototype.wrapEntry_ = function(entry) {
306 if (this.valueCtor_) {
307 if (!entry.valueWrapper) {
308 entry.valueWrapper = new this.valueCtor_(entry.value);
309 }
310 return /** @type {V} */ (entry.valueWrapper);
311 } else {
312 return entry.value;
313 }
314 };
315
316
317 /**
318 * Gets the value corresponding to a key in the map.
319 * @param {K} key
320 * @return {V|undefined} The value, or `undefined` if key not present
321 */
322 jspb.Map.prototype.get = function(key) {
323 var keyValue = key.toString();
324 var entry = this.map_[keyValue];
325 if (entry) {
326 return this.wrapEntry_(entry);
327 } else {
328 return undefined;
329 }
330 };
331
332
333 /**
334 * Determines whether the given key is present in the map.
335 * @param {K} key
336 * @return {boolean} `true` if the key is present
337 */
338 jspb.Map.prototype.has = function(key) {
339 var keyValue = key.toString();
340 return (keyValue in this.map_);
341 };
342
343
344 /**
345 * Write this Map field in wire format to a BinaryWriter, using the given field
346 * number.
347 * @param {number} fieldNumber
348 * @param {!jspb.BinaryWriter} writer
349 * @param {!function(this:jspb.BinaryWriter,number,K)} keyWriterFn
350 * The method on BinaryWriter that writes type K to the stream.
351 * @param {!function(this:jspb.BinaryWriter,number,V)|
352 * function(this:jspb.BinaryReader,V,?)} valueWriterFn
353 * The method on BinaryWriter that writes type V to the stream. May be
354 * writeMessage, in which case the second callback arg form is used.
355 * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
356 * The BinaryWriter serialization callback for type V, if V is a message
357 * type.
358 */
359 jspb.Map.prototype.serializeBinary = function(
360 fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) {
361 var strKeys = this.stringKeys_();
362 strKeys.sort();
363 for (var i = 0; i < strKeys.length; i++) {
364 var entry = this.map_[strKeys[i]];
365 writer.beginSubMessage(fieldNumber);
366 keyWriterFn.call(writer, 1, entry.key);
367 if (this.valueCtor_) {
368 valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
369 opt_valueWriterCallback);
370 } else {
371 valueWriterFn.call(writer, 2, entry.value);
372 }
373 writer.endSubMessage();
374 }
375 };
376
377
378 /**
379 * Read one key/value message from the given BinaryReader. Compatible as the
380 * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called
381 * when a key/value pair submessage is encountered.
382 * @template K, V
383 * @param {!jspb.Map} map
384 * @param {!jspb.BinaryReader} reader
385 * @param {!function(this:jspb.BinaryReader):K} keyReaderFn
386 * The method on BinaryReader that reads type K from the stream.
387 *
388 * @param {!function(this:jspb.BinaryReader):V|
389 * function(this:jspb.BinaryReader,V,
390 * function(V,!jspb.BinaryReader))} valueReaderFn
391 * The method on BinaryReader that reads type V from the stream. May be
392 * readMessage, in which case the second callback arg form is used.
393 *
394 * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
395 * The BinaryReader parsing callback for type V, if V is a message type.
396 *
397 */
398 jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
399 opt_valueReaderCallback) {
400 var key = undefined;
401 var value = undefined;
402
403 while (reader.nextField()) {
404 if (reader.isEndGroup()) {
405 break;
406 }
407 var field = reader.getFieldNumber();
408 if (field == 1) {
409 // Key.
410 key = keyReaderFn.call(reader);
411 } else if (field == 2) {
412 // Value.
413 if (map.valueCtor_) {
414 value = new map.valueCtor_();
415 valueReaderFn.call(reader, value, opt_valueReaderCallback);
416 } else {
417 value = valueReaderFn.call(reader);
418 }
419 }
420 }
421
422 goog.asserts.assert(key != undefined);
423 goog.asserts.assert(value != undefined);
424 map.set(key, value);
425 };
426
427
428 /**
429 * Helper: compute the list of all stringified keys in the underlying Object
430 * map.
431 * @return {!Array<string>}
432 * @private
433 */
434 jspb.Map.prototype.stringKeys_ = function() {
435 var m = this.map_;
436 var ret = [];
437 for (var p in m) {
438 if (Object.prototype.hasOwnProperty.call(m, p)) {
439 ret.push(p);
440 }
441 }
442 return ret;
443 };
444
445
446
447 /**
448 * @param {!K} key The entry's key.
449 * @param {V=} opt_value The entry's value wrapper.
450 * @constructor
451 * @struct
452 * @template K, V
453 * @private
454 */
455 jspb.Map.Entry_ = function(key, opt_value) {
456 /** @const {K} */
457 this.key = key;
458
459 // The JSPB-serializable value. For primitive types this will be of type V.
460 // For message types it will be an array.
461 /** @type {V} */
462 this.value = opt_value;
463
464 // Only used for submessage values.
465 /** @type {V} */
466 this.valueWrapper = undefined;
467 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698