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

Side by Side Diff: lib/protobuf/runtime/Builder.dart

Issue 10595002: Protocol Buffer runtime library and 'protoc' plugin (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Work around http://code.google.com/p/dart/issues/detail?id=3806 Created 8 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « lib/protobuf/plugin/protoc/plugin.pb.dart ('k') | lib/protobuf/runtime/BuilderInfo.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 typedef Builder CreateBuilderFunc();
6 typedef Object MakeDefaultFunc();
7 typedef ProtobufEnum ValueOfFunc(int value);
8
9 class Builder implements ChangeListener {
10 static final int _REQUIRED_BIT = 0x1;
11 static final int _REPEATED_BIT = 0x2;
12 static final int _PACKED_BIT = 0x4;
13
14 static final int _BOOL_BIT = 0x10;
15 static final int _BYTES_BIT = 0x20;
16 static final int _STRING_BIT = 0x40;
17 static final int _DOUBLE_BIT = 0x80;
18 static final int _FLOAT_BIT = 0x100;
19 static final int _ENUM_BIT = 0x200;
20 static final int _GROUP_BIT = 0x400;
21 static final int _INT32_BIT = 0x800;
22 static final int _INT64_BIT = 0x1000;
23 static final int _SINT32_BIT = 0x2000;
24 static final int _SINT64_BIT = 0x4000;
25 static final int _UINT32_BIT = 0x8000;
26 static final int _UINT64_BIT = 0x10000;
27 static final int _FIXED32_BIT = 0x20000;
28 static final int _FIXED64_BIT = 0x40000;
29 static final int _SFIXED32_BIT = 0x80000;
30 static final int _SFIXED64_BIT = 0x100000;
31 static final int _MESSAGE_BIT = 0x200000;
32
33 static final int _OPTIONAL_BOOL = _BOOL_BIT;
34 static final int _OPTIONAL_BYTES = _BYTES_BIT;
35 static final int _OPTIONAL_STRING = _STRING_BIT;
36 static final int _OPTIONAL_FLOAT = _FLOAT_BIT;
37 static final int _OPTIONAL_DOUBLE = _DOUBLE_BIT;
38 static final int _OPTIONAL_ENUM = _ENUM_BIT;
39 static final int _OPTIONAL_GROUP = _GROUP_BIT;
40 static final int _OPTIONAL_INT32 = _INT32_BIT;
41 static final int _OPTIONAL_INT64 = _INT64_BIT;
42 static final int _OPTIONAL_SINT32 = _SINT32_BIT;
43 static final int _OPTIONAL_SINT64 = _SINT64_BIT;
44 static final int _OPTIONAL_UINT32 = _UINT32_BIT;
45 static final int _OPTIONAL_UINT64 = _UINT64_BIT;
46 static final int _OPTIONAL_FIXED32 = _FIXED32_BIT;
47 static final int _OPTIONAL_FIXED64 = _FIXED64_BIT;
48 static final int _OPTIONAL_SFIXED32 = _SFIXED32_BIT;
49 static final int _OPTIONAL_SFIXED64 = _SFIXED64_BIT;
50 static final int _OPTIONAL_MESSAGE = _MESSAGE_BIT;
51
52 static final int _REQUIRED_BOOL = _REQUIRED_BIT | _BOOL_BIT;
53 static final int _REQUIRED_BYTES = _REQUIRED_BIT | _BYTES_BIT;
54 static final int _REQUIRED_STRING = _REQUIRED_BIT | _STRING_BIT;
55 static final int _REQUIRED_FLOAT = _REQUIRED_BIT | _FLOAT_BIT;
56 static final int _REQUIRED_DOUBLE = _REQUIRED_BIT | _DOUBLE_BIT;
57 static final int _REQUIRED_ENUM = _REQUIRED_BIT | _ENUM_BIT;
58 static final int _REQUIRED_GROUP = _REQUIRED_BIT | _GROUP_BIT;
59 static final int _REQUIRED_INT32 = _REQUIRED_BIT | _INT32_BIT;
60 static final int _REQUIRED_INT64 = _REQUIRED_BIT | _INT64_BIT;
61 static final int _REQUIRED_SINT32 = _REQUIRED_BIT | _SINT32_BIT;
62 static final int _REQUIRED_SINT64 = _REQUIRED_BIT | _SINT64_BIT;
63 static final int _REQUIRED_UINT32 = _REQUIRED_BIT | _UINT32_BIT;
64 static final int _REQUIRED_UINT64 = _REQUIRED_BIT | _UINT64_BIT;
65 static final int _REQUIRED_FIXED32 = _REQUIRED_BIT | _FIXED32_BIT;
66 static final int _REQUIRED_FIXED64 = _REQUIRED_BIT | _FIXED64_BIT;
67 static final int _REQUIRED_SFIXED32 = _REQUIRED_BIT | _SFIXED32_BIT;
68 static final int _REQUIRED_SFIXED64 = _REQUIRED_BIT | _SFIXED64_BIT;
69 static final int _REQUIRED_MESSAGE = _REQUIRED_BIT | _MESSAGE_BIT;
70
71 static final int _REPEATED_BOOL = _REPEATED_BIT | _BOOL_BIT;
72 static final int _REPEATED_BYTES = _REPEATED_BIT | _BYTES_BIT;
73 static final int _REPEATED_STRING = _REPEATED_BIT | _STRING_BIT;
74 static final int _REPEATED_FLOAT = _REPEATED_BIT | _FLOAT_BIT;
75 static final int _REPEATED_DOUBLE = _REPEATED_BIT | _DOUBLE_BIT;
76 static final int _REPEATED_ENUM = _REPEATED_BIT | _ENUM_BIT;
77 static final int _REPEATED_GROUP = _REPEATED_BIT | _GROUP_BIT;
78 static final int _REPEATED_INT32 = _REPEATED_BIT | _INT32_BIT;
79 static final int _REPEATED_INT64 = _REPEATED_BIT | _INT64_BIT;
80 static final int _REPEATED_SINT32 = _REPEATED_BIT | _SINT32_BIT;
81 static final int _REPEATED_SINT64 = _REPEATED_BIT | _SINT64_BIT;
82 static final int _REPEATED_UINT32 = _REPEATED_BIT | _UINT32_BIT;
83 static final int _REPEATED_UINT64 = _REPEATED_BIT | _UINT64_BIT;
84 static final int _REPEATED_FIXED32 = _REPEATED_BIT | _FIXED32_BIT;
85 static final int _REPEATED_FIXED64 = _REPEATED_BIT | _FIXED64_BIT;
86 static final int _REPEATED_SFIXED32 = _REPEATED_BIT | _SFIXED32_BIT;
87 static final int _REPEATED_SFIXED64 = _REPEATED_BIT | _SFIXED64_BIT;
88 static final int _REPEATED_MESSAGE = _REPEATED_BIT | _MESSAGE_BIT;
89
90 static final int _PACKED_BOOL = _REPEATED_BIT | _PACKED_BIT | _BOOL_BIT;
91 static final int _PACKED_FLOAT = _REPEATED_BIT | _PACKED_BIT | _FLOAT_BIT;
92 static final int _PACKED_DOUBLE = _REPEATED_BIT | _PACKED_BIT | _DOUBLE_BIT;
93 static final int _PACKED_ENUM = _REPEATED_BIT | _PACKED_BIT | _ENUM_BIT;
94 static final int _PACKED_INT32 = _REPEATED_BIT | _PACKED_BIT | _INT32_BIT;
95 static final int _PACKED_INT64 = _REPEATED_BIT | _PACKED_BIT | _INT64_BIT;
96 static final int _PACKED_SINT32 = _REPEATED_BIT | _PACKED_BIT | _SINT32_BIT;
97 static final int _PACKED_SINT64 = _REPEATED_BIT | _PACKED_BIT | _SINT64_BIT;
98 static final int _PACKED_UINT32 = _REPEATED_BIT | _PACKED_BIT | _UINT32_BIT;
99 static final int _PACKED_UINT64 = _REPEATED_BIT | _PACKED_BIT | _UINT64_BIT;
100 static final int _PACKED_FIXED32 = _REPEATED_BIT | _PACKED_BIT | _FIXED32_BIT;
101 static final int _PACKED_FIXED64 = _REPEATED_BIT | _PACKED_BIT | _FIXED64_BIT;
102 static final int _PACKED_SFIXED32 = _REPEATED_BIT | _PACKED_BIT |
103 _SFIXED32_BIT;
104 static final int _PACKED_SFIXED64 = _REPEATED_BIT | _PACKED_BIT |
105 _SFIXED64_BIT;
106
107 // Short names for use in generated code
108
109 // _O_ptional
110 static final int OB = _OPTIONAL_BOOL;
111 static final int OY = _OPTIONAL_BYTES;
112 static final int OS = _OPTIONAL_STRING;
113 static final int OF = _OPTIONAL_FLOAT;
114 static final int OD = _OPTIONAL_DOUBLE;
115 static final int OE = _OPTIONAL_ENUM;
116 static final int OG = _OPTIONAL_GROUP;
117 static final int O3 = _OPTIONAL_INT32;
118 static final int O6 = _OPTIONAL_INT64;
119 static final int OS3 = _OPTIONAL_SINT32;
120 static final int OS6 = _OPTIONAL_SINT64;
121 static final int OU3 = _OPTIONAL_UINT32;
122 static final int OU6 = _OPTIONAL_UINT64;
123 static final int OF3 = _OPTIONAL_FIXED32;
124 static final int OF6 = _OPTIONAL_FIXED64;
125 static final int OSF3 = _OPTIONAL_SFIXED32;
126 static final int OSF6 = _OPTIONAL_SFIXED64;
127 static final int OM = _OPTIONAL_MESSAGE;
128
129 // re_Q_uired
130 static final int QB = _REQUIRED_BOOL;
131 static final int QY = _REQUIRED_BYTES;
132 static final int QS = _REQUIRED_STRING;
133 static final int QF = _REQUIRED_FLOAT;
134 static final int QD = _REQUIRED_DOUBLE;
135 static final int QE = _REQUIRED_ENUM;
136 static final int QG = _REQUIRED_GROUP;
137 static final int Q3 = _REQUIRED_INT32;
138 static final int Q6 = _REQUIRED_INT64;
139 static final int QS3 = _REQUIRED_SINT32;
140 static final int QS6 = _REQUIRED_SINT64;
141 static final int QU3 = _REQUIRED_UINT32;
142 static final int QU6 = _REQUIRED_UINT64;
143 static final int QF3 = _REQUIRED_FIXED32;
144 static final int QF6 = _REQUIRED_FIXED64;
145 static final int QSF3 = _REQUIRED_SFIXED32;
146 static final int QSF6 = _REQUIRED_SFIXED64;
147 static final int QM = _REQUIRED_MESSAGE;
148
149 // re_P_eated
150 static final int PB = _REPEATED_BOOL;
151 static final int PY = _REPEATED_BYTES;
152 static final int PS = _REPEATED_STRING;
153 static final int PF = _REPEATED_FLOAT;
154 static final int PD = _REPEATED_DOUBLE;
155 static final int PE = _REPEATED_ENUM;
156 static final int PG = _REPEATED_GROUP;
157 static final int P3 = _REPEATED_INT32;
158 static final int P6 = _REPEATED_INT64;
159 static final int PS3 = _REPEATED_SINT32;
160 static final int PS6 = _REPEATED_SINT64;
161 static final int PU3 = _REPEATED_UINT32;
162 static final int PU6 = _REPEATED_UINT64;
163 static final int PF3 = _REPEATED_FIXED32;
164 static final int PF6 = _REPEATED_FIXED64;
165 static final int PSF3 = _REPEATED_SFIXED32;
166 static final int PSF6 = _REPEATED_SFIXED64;
167 static final int PM = _REPEATED_MESSAGE;
168
169 // pac_K_ed
170 static final int KB = _PACKED_BOOL;
171 static final int KE = _PACKED_ENUM;
172 static final int KF = _PACKED_FLOAT;
173 static final int KD = _PACKED_DOUBLE;
174 static final int K3 = _PACKED_INT32;
175 static final int K6 = _PACKED_INT64;
176 static final int KS3 = _PACKED_SINT32;
177 static final int KS6 = _PACKED_SINT64;
178 static final int KU3 = _PACKED_UINT32;
179 static final int KU6 = _PACKED_UINT64;
180 static final int KF3 = _PACKED_FIXED32;
181 static final int KF6 = _PACKED_FIXED64;
182 static final int KSF3 = _PACKED_SFIXED32;
183 static final int KSF6 = _PACKED_SFIXED64;
184
185 // Closures commonly used by initializers
186 static MakeDefaultFunc __STRING_EMPTY; // () => ''
187 static MakeDefaultFunc __BYTES_EMPTY; // () => <int>[]
188 static MakeDefaultFunc __BOOL_FALSE; // () => false
189 static MakeDefaultFunc __INT_ZERO; // () => 0
190 static MakeDefaultFunc __DOUBLE_ZERO; // () => 0.0
191
192 static MakeDefaultFunc get _STRING_EMPTY() {
193 if (__STRING_EMPTY === null) {
194 __STRING_EMPTY = () => '';
195 }
196 return __STRING_EMPTY;
197 }
198
199 static MakeDefaultFunc get _BYTES_EMPTY() {
200 if (__BYTES_EMPTY === null) {
201 __BYTES_EMPTY = () => <int>[];
202 }
203 return __BYTES_EMPTY;
204 }
205
206 static MakeDefaultFunc get _BOOL_FALSE() {
207 if (__BOOL_FALSE === null) {
208 __BOOL_FALSE = () => false;
209 }
210 return __BOOL_FALSE;
211 }
212
213 static MakeDefaultFunc get _INT_ZERO() {
214 if (__INT_ZERO === null) {
215 __INT_ZERO = () => 0;
216 }
217 return __INT_ZERO;
218 }
219
220 static MakeDefaultFunc get _DOUBLE_ZERO() {
221 if (__DOUBLE_ZERO === null) {
222 __DOUBLE_ZERO = () => 0.0;
223 }
224 return __DOUBLE_ZERO;
225 }
226
227 static MakeDefaultFunc _defaultForType(int type) {
228 switch (type) {
229 case _OPTIONAL_BOOL: case _REQUIRED_BOOL:
230 return _BOOL_FALSE;
231 case _OPTIONAL_BYTES: case _REQUIRED_BYTES:
232 return _BYTES_EMPTY;
233 case _OPTIONAL_STRING: case _REQUIRED_STRING:
234 return _STRING_EMPTY;
235 case _OPTIONAL_FLOAT: case _REQUIRED_FLOAT:
236 case _OPTIONAL_DOUBLE: case _REQUIRED_DOUBLE:
237 return _DOUBLE_ZERO;
238 case _OPTIONAL_INT32: case _REQUIRED_INT32:
239 case _OPTIONAL_INT64: case _REQUIRED_INT64:
240 case _OPTIONAL_SINT32: case _REQUIRED_SINT32:
241 case _OPTIONAL_SINT64: case _REQUIRED_SINT64:
242 case _OPTIONAL_UINT32: case _REQUIRED_UINT32:
243 case _OPTIONAL_UINT64: case _REQUIRED_UINT64:
244 case _OPTIONAL_FIXED32: case _REQUIRED_FIXED32:
245 case _OPTIONAL_FIXED64: case _REQUIRED_FIXED64:
246 case _OPTIONAL_SFIXED32: case _REQUIRED_SFIXED32:
247 case _OPTIONAL_SFIXED64: case _REQUIRED_SFIXED64:
248 return _INT_ZERO;
249 default:
250 return null;
251 }
252 }
253
254 static Function _converterForType(int type) {
255 if (((type & _REPEATED_BIT) != 0) || ((type & _PACKED_BIT) != 0)) {
256 return ((type & _BYTES_BIT) != 0) ?
257 _toImmutableListNonGrowable : _toImmutableListIdentity;
258 } else {
259 return ((type & _BYTES_BIT) != 0) ? _toNonGrowableList : _identity;
260 }
261 }
262
263 static Object _identity(Object source) => source;
264
265 static List _toNonGrowableList(List source) {
266 if (source is PbImmutableList) {
267 return source;
268 } else {
269 return new PbImmutableList.from(source);
270 }
271 }
272
273 static List _toImmutableListIdentity(PbList source) {
274 return source.asImmutable();
275 }
276
277 static List _toImmutableListNonGrowable(PbList source) {
278 return source.asImmutable(_toNonGrowableList);
279 }
280
281 Map<int, Dynamic> _fieldValues;
282 bool _isClean;
283 UnknownFieldSet _unknownFields;
284 Map<int, Extension> _extensions;
285
286 Builder()
287 : _unknownFields = UnknownFieldSet.defaultInstance,
288 _fieldValues = new Map<int, Dynamic>() {
289 initialize_();
290 }
291
292 /**
293 * Add an extension field value to a repeated field. The backing
294 * [List] will be created if necessary.
295 */
296 void addExtension(Extension extension, var value) {
297 _checkExtension(extension);
298 if ((extension.type & _REPEATED_BIT) == 0) {
299 throw new PbException(
300 "Cannot add to a non-repeated field (use 'setExtension()')");
301 }
302 // Validate type and range
303 value = _validate(extension.tagNumber, extension.type & ~0x7, value);
304
305 var list = _fieldValues[extension.tagNumber];
306 if (list == null) {
307 list = extension.makeDefault();
308 _setExtension(extension, list);
309 }
310
311 list.add(value);
312 onChanged();
313 }
314
315 Message build() {
316 Message result = buildPartial();
317 if (!isInitialized()) {
318 List<String> invalidFields = <String>[];
319 _findInvalidFields(invalidFields);
320 throw new UninitializedMessageException(invalidFields);
321 }
322 return result;
323 }
324
325 Message buildParsed() {
326 Message result = buildPartial();
327 if (!isInitialized()) {
328 List<String> invalidFields = <String>[];
329 _findInvalidFields(invalidFields);
330 throw new UninitializedMessageException(invalidFields);
331 }
332 return result;
333 }
334
335 abstract Message buildPartial();
336
337 // Shorthand for clearField
338 void c_(int tagNumber) {
339 clearField(tagNumber);
340 }
341
342 void clear() {
343 _unknownFields = UnknownFieldSet.defaultInstance;
344 _fieldValues = new Map<int, Dynamic>();
345 _isClean = true;
346 }
347
348 void clearExtension(Extension extension) {
349 _checkExtension(extension);
350 _fieldValues.remove(extension.tagNumber);
351 Object value = extension.makeDefault();
352 if (value is List) {
353 _setExtension(extension, value);
354 } else {
355 _extensions.remove(extension.tagNumber);
356 }
357 }
358
359 void clearField(int tagNumber) {
360 _fieldValues.remove(tagNumber);
361 // Restore the default value for the field
362 // For repeated fields, the default is an empty list
363 // For required/optional fields, the BuilderInfo contains the initializer
364 int fieldType = _getFieldType(tagNumber);
365 if ((fieldType & _REPEATED_BIT) != 0) {
366 _fieldValues[tagNumber] = new PbList(this);
367 } else {
368 Object defaultValue = info_.defaultValue(tagNumber);
369 if (defaultValue !== null) {
370 _fieldValues[tagNumber] = defaultValue;
371 }
372 }
373 }
374
375 bool extensionsAreInitialized() {
376 if (_extensions == null) {
377 return true;
378 }
379 return _extensions.getKeys().every(bool _(int tagNumber) {
380 return info_._isFieldInitialized(_fieldValues, tagNumber,
381 _extensions[tagNumber].type);
382 });
383 }
384
385 // Allow the contents of each map or set to be changed, but not its reference
386 Map<int, Object> get fieldValues() {
387 // Force initialization of field values to defaults
388 if (info_ !== null) {
389 for (FieldInfo i in info_.fieldInfo.getValues()) {
390 if (i.makeDefault != null) fieldValues [i.tagNumber] = i.makeDefault();
391 }
392 }
393 return _fieldValues;
394 }
395
396 /**
397 * Shorthand for [:getField(tagNumber):].
398 */
399 Dynamic g_(int tagNumber) => getField(tagNumber);
400
401 /**
402 * Returns the value of the given extension. For repeated fields that have
403 * not been set previously, [:null:] is returned.
404 */
405 Dynamic getExtension(Extension extension) {
406 _checkExtension(extension);
407 return getField(extension.tagNumber);
408 }
409
410 /**
411 * Returns the number of elements in the given extension. For repeated fields
412 * that have not been set previously, or for non-repeated fields, [:0:] is
413 * returned.
414 */
415 int getExtensionCount(Extension extension) {
416 _checkExtension(extension);
417 List list = _fieldValues[extension.tagNumber];
418 return (list === null || list is! List) ? 0 : list.length;
419 }
420
421 Object getField(int tagNumber) {
422 var value = _fieldValues[tagNumber];
423 // Initialize the field
424 if (value === null) {
425 MakeDefaultFunc makeDefaultFunc = info_.makeDefault(tagNumber);
426 if (makeDefaultFunc == null) {
427 makeDefaultFunc = _extensions[tagNumber].makeDefault;
428 if (makeDefaultFunc == null) {
429 throw new PbException("Can't make default for field "
430 "${info_.fieldName(tagNumber)} in message ${info_.messageName}");
431 }
432 }
433 value = makeDefaultFunc();
434 _fieldValues[tagNumber] = value;
435 }
436 return value;
437 }
438
439 // Shorthand for hasField
440 bool h_(int tagNumber) => hasField(tagNumber);
441
442 /**
443 * Return [:true:] if a value of the given extension is present.
444 */
445 bool hasExtension(Extension extension) {
446 _checkExtension(extension);
447 return hasField(extension.tagNumber);
448 }
449
450 bool hasField(int tagNumber) {
451 int fieldType = info_.fieldType(tagNumber);
452 if (!_fieldValues.containsKey(tagNumber)) {
453 return false;
454 }
455 var value = _fieldValues[tagNumber];
456 if (value is List && value.isEmpty()) {
457 return false;
458 }
459 return true;
460 }
461
462 // Overriden by subclasses
463 abstract BuilderInfo get info_();
464
465 abstract void initialize_();
466
467 bool isInitialized() {
468 if (!info_.hasRequiredFields) {
469 return true;
470 }
471 return info_.isInitialized(_fieldValues) && extensionsAreInitialized();
472 }
473
474 Builder mergeFromBuffer(List<int> input,
475 [ExtensionRegistry extensionRegistry]) {
476 CodedBufferReader codedInput = new CodedBufferReader.fromBuffer(input);
477 extensionRegistry = extensionRegistry == null ?
478 ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
479 mergeFromCodedBufferReader(codedInput, extensionRegistry);
480 codedInput.checkLastTagWas(0);
481 return this;
482 }
483
484 Builder mergeFromCodedBufferReader(CodedBufferReader input,
485 [ExtensionRegistry extensionRegistry]) {
486 UnknownFieldSet_Builder unknownFieldSetBuilder =
487 new UnknownFieldSet_Builder(unknownFields);
488 extensionRegistry = extensionRegistry == null ?
489 ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
490
491 void readPackableIoc(int wireType, int tagNumber, var iocReadFunc) {
492 List list = getField(tagNumber);
493 if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
494 // Packed
495 int length = input.readInt32();
496 int limit = input._pushLimit(length);
497 while (input.getBytesUntilLimit() > 0) {
498 iocReadFunc((var v) => list.add(v));
499 }
500 input._popLimit(limit);
501 } else {
502 // Not-packed
503 iocReadFunc((var v) => list.add(v));
504 }
505 }
506
507 void readPackable(int wireType, int tagNumber, var readFunc) {
508 readPackableIoc(wireType, tagNumber,
509 (var assigner) => assigner(readFunc()));
510 }
511
512 bool wireTypeMatch(int tagNumber, int fieldType, int wireType) {
513 int fieldDataType = fieldType &
514 ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT);
515 switch (fieldDataType) {
516 case _BOOL_BIT:
517 case _ENUM_BIT:
518 case _INT32_BIT:
519 case _INT64_BIT:
520 case _SINT32_BIT:
521 case _SINT64_BIT:
522 case _UINT32_BIT:
523 case _UINT64_BIT:
524 return wireType == WireFormat.WIRETYPE_VARINT ||
525 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
526 case _FLOAT_BIT:
527 case _FIXED32_BIT:
528 case _SFIXED32_BIT:
529 return wireType == WireFormat.WIRETYPE_FIXED32 ||
530 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
531 case _DOUBLE_BIT:
532 case _FIXED64_BIT:
533 case _SFIXED64_BIT:
534 return wireType == WireFormat.WIRETYPE_FIXED64 ||
535 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
536 case _BYTES_BIT:
537 case _STRING_BIT:
538 case _MESSAGE_BIT:
539 return wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
540 case _GROUP_BIT:
541 return wireType == WireFormat.WIRETYPE_START_GROUP;
542 default:
543 return false;
544 }
545 }
546
547 while (true) {
548 int tag = input.readTag();
549 if (tag == 0) {
550 unknownFields = unknownFieldSetBuilder.build();
551 onChanged();
552 return this;
553 }
554 int wireType = tag & 0x7;
555 int tagNumber = tag >> 3;
556 int fieldType = -1;
557
558 if (info_ != null) {
559 if (info_.containsTagNumber(tagNumber)) {
560 fieldType = info_.fieldType(tagNumber);
561 } else {
562 Extension extension = extensionRegistry
563 .getExtension(info_.messageName, tagNumber);
564 if (extension != null) {
565 _addExtensionToMap(extension);
566 fieldType = extension.type;
567 }
568 }
569 }
570 if (fieldType == -1 || !wireTypeMatch(tagNumber, fieldType, wireType)) {
571 if (!parseUnknownFieldFromBuffer(input, unknownFieldSetBuilder, tag)) {
572 unknownFields = unknownFieldSetBuilder.build();
573 onChanged();
574 return this;
575 } else {
576 continue;
577 }
578 }
579
580 // ignore required/optional packed/unpacked
581 fieldType &= ~(_PACKED_BIT | _REQUIRED_BIT);
582 switch (fieldType) {
583 case _OPTIONAL_BOOL:
584 _fieldValues[tagNumber] = input.readBool();
585 break;
586 case _OPTIONAL_BYTES:
587 _fieldValues[tagNumber] = input.readBytes();
588 break;
589 case _OPTIONAL_STRING:
590 _fieldValues[tagNumber] = input.readString();
591 break;
592 case _OPTIONAL_FLOAT:
593 _fieldValues[tagNumber] = input.readFloat();
594 break;
595 case _OPTIONAL_DOUBLE:
596 _fieldValues[tagNumber] = input.readDouble();
597 break;
598 case _OPTIONAL_ENUM:
599 int rawValue = input.readEnum();
600 var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
601 if (value == null) {
602 unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
603 } else {
604 _fieldValues[tagNumber] = value;
605 }
606 break;
607 case _OPTIONAL_GROUP:
608 Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
609 if (_fieldValues.containsKey(tagNumber)) {
610 subBuilder.mergeFromMessage(getField(tagNumber));
611 }
612 input.readGroup(tagNumber, subBuilder, extensionRegistry);
613 _fieldValues[tagNumber] = subBuilder.buildPartial();
614 break;
615 case _OPTIONAL_INT32:
616 _fieldValues[tagNumber] = input.readInt32();
617 break;
618 case _OPTIONAL_INT64:
619 _fieldValues[tagNumber] = input.readInt64();
620 break;
621 case _OPTIONAL_SINT32:
622 _fieldValues[tagNumber] = input.readSint32();
623 break;
624 case _OPTIONAL_SINT64:
625 _fieldValues[tagNumber] = input.readSint64();
626 break;
627 case _OPTIONAL_UINT32:
628 _fieldValues[tagNumber] = input.readUint32();
629 break;
630 case _OPTIONAL_UINT64:
631 _fieldValues[tagNumber] = input.readUint64();
632 break;
633 case _OPTIONAL_FIXED32:
634 _fieldValues[tagNumber] = input.readFixed32();
635 break;
636 case _OPTIONAL_FIXED64:
637 _fieldValues[tagNumber] = input.readFixed64();
638 break;
639 case _OPTIONAL_SFIXED32:
640 _fieldValues[tagNumber] = input.readSfixed32();
641 break;
642 case _OPTIONAL_SFIXED64:
643 _fieldValues[tagNumber] = input.readSfixed64();
644 break;
645 case _OPTIONAL_MESSAGE:
646 Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
647 if (_fieldValues.containsKey(tagNumber)) {
648 subBuilder.mergeFromMessage(getField(tagNumber));
649 }
650 input.readMessage(subBuilder, extensionRegistry);
651 _fieldValues[tagNumber] = subBuilder.buildPartial();
652 break;
653 case _REPEATED_BOOL:
654 readPackable(wireType, tagNumber, input.readBool);
655 break;
656 case _REPEATED_BYTES:
657 List list = getField(tagNumber);
658 list.add(input.readBytes());
659 break;
660 case _REPEATED_STRING:
661 List list = getField(tagNumber);
662 list.add(input.readString());
663 break;
664 case _REPEATED_FLOAT:
665 readPackable(wireType, tagNumber, input.readFloat);
666 break;
667 case _REPEATED_DOUBLE:
668 readPackable(wireType, tagNumber, input.readDouble);
669 break;
670 case _REPEATED_ENUM:
671 readPackableIoc(wireType, tagNumber, (var assigner){
672 int rawValue = input.readEnum();
673 var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
674 if (value == null) {
675 unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
676 } else {
677 assigner(value);
678 }
679 });
680 break;
681 case _REPEATED_GROUP:
682 Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
683 input.readGroup(tagNumber, subBuilder, extensionRegistry);
684 List list = getField(tagNumber);
685 list.add(subBuilder.buildPartial());
686 break;
687 case _REPEATED_INT32:
688 readPackable(wireType, tagNumber, input.readInt32);
689 break;
690 case _REPEATED_INT64:
691 readPackable(wireType, tagNumber, input.readInt64);
692 break;
693 case _REPEATED_SINT32:
694 readPackable(wireType, tagNumber, input.readSint32);
695 break;
696 case _REPEATED_SINT64:
697 readPackable(wireType, tagNumber, input.readSint64);
698 break;
699 case _REPEATED_UINT32:
700 readPackable(wireType, tagNumber, input.readUint32);
701 break;
702 case _REPEATED_UINT64:
703 readPackable(wireType, tagNumber, input.readUint64);
704 break;
705 case _REPEATED_FIXED32:
706 readPackable(wireType, tagNumber, input.readFixed32);
707 break;
708 case _REPEATED_FIXED64:
709 readPackable(wireType, tagNumber, input.readFixed64);
710 break;
711 case _REPEATED_SFIXED32:
712 readPackable(wireType, tagNumber, input.readSfixed32);
713 break;
714 case _REPEATED_SFIXED64:
715 readPackable(wireType, tagNumber, input.readSfixed64);
716 break;
717 case _REPEATED_MESSAGE:
718 Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
719 input.readMessage(subBuilder, extensionRegistry);
720 List list = getField(tagNumber);
721 list.add(subBuilder.buildPartial());
722 break;
723 default:
724 throw "Unknown field type $fieldType";
725 }
726 }
727 }
728
729 /**
730 * Merge field values from a JSON object, encoded as described by
731 * [GeneratedMessage.writeToJson].
732 */
733 Builder mergeFromJson(String json, [ExtensionRegistry extensionRegistry]) {
734 extensionRegistry = extensionRegistry == null ?
735 ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
736 Map<String, Object> parsed = JSON.parse(json);
737 _mergeFromJson(parsed, extensionRegistry);
738 return this;
739 }
740
741 Builder mergeFromMessage(GeneratedMessage other) {
742 for (int tagNumber in other._fieldValues.getKeys()) {
743 var fieldValue = other._fieldValues[tagNumber];
744
745 int fieldType = other._builderInfo.fieldType(tagNumber);
746 if (fieldType != null) {
747 if ((fieldType & _REPEATED_BIT) != 0) {
748 List otherList = fieldValue;
749 if (!otherList.isEmpty()) {
750 List thisList = getField(tagNumber);
751 thisList.addAll(otherList);
752 onChanged();
753 }
754 } else {
755 setField(tagNumber, fieldValue);
756 }
757 } else {
758 Extension extension = other._extensions[tagNumber];
759 _addExtensionToMap(extension);
760 fieldType = extension.type;
761 if ((fieldType & _REPEATED_BIT) != 0) {
762 List otherList = fieldValue;
763 if (!otherList.isEmpty()) {
764 List thisList = extension.makeDefault();
765 thisList.addAll(otherList);
766 _fieldValues[tagNumber] = thisList;
767 onChanged();
768 }
769 } else {
770 setField(tagNumber, fieldValue, fieldType);
771 }
772 }
773 }
774
775 mergeUnknownFields(other.unknownFields);
776 return this;
777 }
778
779 Future<Builder> mergeFromCodedStreamReader(CodedStreamReader input,
780 [ExtensionRegistry extensionRegistry]) {
781 UnknownFieldSet_Builder unknownFieldSetBuilder =
782 new UnknownFieldSet_Builder(unknownFields);
783 extensionRegistry = extensionRegistry == null ?
784 ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
785 Completer<Builder> c = new Completer<Builder>();
786
787 Function merge;
788
789 Function appendAndMerge(int tagNumber) {
790 return Future _(Dynamic value) {
791 List list = getField(tagNumber);
792 list.add(value);
793 return merge();
794 };
795 }
796
797 Function assignAndMerge(int tagNumber) {
798 return Future _(Dynamic value) {
799 _fieldValues[tagNumber] = value;
800 return merge();
801 };
802 }
803
804 // readPackableIoc inverts control in that it takes in a read function
805 // that itself takes a function parameter. This function actually sets the
806 // value in the current message. This is important because the setter method
807 // may need to be substituted in the case that an enum is unresolved.
808 Future readPackableIoc(int wireType, int tagNumber, var iocReadFunc) {
809 List list = getField(tagNumber);
810 if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
811 // Packed
812 return input.readInt32().chain((int length) {
813 int limit = input._pushLimit(length);
814 Future readUntilLimit() {
815 if (input.getBytesUntilLimit() > 0) {
816 return iocReadFunc((var v) => list.add(v))
817 .chain(() => readUntilLimit());
818 } else {
819 input._popLimit(limit);
820 return merge();
821 }
822 }
823 });
824 } else {
825 // Not-packed
826 return iocReadFunc((var v) => list.add(v)).chain((_) => merge());
827 }
828 }
829
830 Future readPackable(int wireType, int tagNumber, var readFunc) =>
831 readPackableIoc(wireType, tagNumber, _(var assigner) =>
832 readFunc().transform((v) => assigner(v))
833 );
834
835 bool wireTypeMatch(int tagNumber, int fieldType, int wireType) {
836 int fieldDataType = fieldType &
837 ~(Builder._REQUIRED_BIT | Builder._REPEATED_BIT |
838 Builder._PACKED_BIT);
839 switch (fieldDataType) {
840 case Builder._BOOL_BIT:
841 case Builder._ENUM_BIT:
842 case Builder._INT32_BIT:
843 case Builder._INT64_BIT:
844 case Builder._SINT32_BIT:
845 case Builder._SINT64_BIT:
846 case Builder._UINT32_BIT:
847 case Builder._UINT64_BIT:
848 return wireType == WireFormat.WIRETYPE_VARINT ||
849 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
850 case Builder._FLOAT_BIT:
851 case Builder._FIXED32_BIT:
852 case Builder._SFIXED32_BIT:
853 return wireType == WireFormat.WIRETYPE_FIXED32 ||
854 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
855 case Builder._DOUBLE_BIT:
856 case Builder._FIXED64_BIT:
857 case Builder._SFIXED64_BIT:
858 return wireType == WireFormat.WIRETYPE_FIXED64 ||
859 wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
860 case Builder._BYTES_BIT:
861 case Builder._STRING_BIT:
862 case Builder._MESSAGE_BIT:
863 return wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
864 case Builder._GROUP_BIT:
865 return wireType == WireFormat.WIRETYPE_START_GROUP;
866 default:
867 return false;
868 }
869 }
870
871 Future readField(int tagNumber, int wireType, int fieldType) {
872 // ignore required/optional packed/unpacked
873 fieldType &= ~(Builder._PACKED_BIT | Builder._REQUIRED_BIT);
874 switch (fieldType) {
875 case Builder._OPTIONAL_BOOL:
876 return input.readBool().chain(assignAndMerge(tagNumber));
877 case Builder._OPTIONAL_BYTES:
878 return input.readBytes().chain(assignAndMerge(tagNumber));
879 case Builder._OPTIONAL_STRING:
880 return input.readString().chain(assignAndMerge(tagNumber));
881 case Builder._OPTIONAL_FLOAT:
882 return input.readFloat().chain(assignAndMerge(tagNumber));
883 case Builder._OPTIONAL_DOUBLE:
884 return input.readDouble().chain(assignAndMerge(tagNumber));
885 case Builder._OPTIONAL_ENUM:
886 return input.readEnum().chain((int rawValue) {
887 var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
888 if (value == null) {
889 unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
890 } else {
891 _fieldValues[tagNumber] = value;
892 }
893 return merge();
894 });
895 case Builder._OPTIONAL_GROUP:
896 Builder subBuilder = info_.subBuilder(tagNumber)();
897 if (_fieldValues.containsKey(tagNumber)) {
898 subBuilder.mergeFromMessage(getField(tagNumber));
899 }
900 return input.readGroup(tagNumber, subBuilder, extensionRegistry)
901 .chain((_) {
902 _fieldValues[tagNumber] = subBuilder.buildPartial();
903 return merge();
904 });
905 case Builder._OPTIONAL_INT32:
906 return input.readInt32().chain(assignAndMerge(tagNumber));
907 case Builder._OPTIONAL_INT64:
908 return input.readInt64().chain(assignAndMerge(tagNumber));
909 case Builder._OPTIONAL_SINT32:
910 return input.readSint32().chain(assignAndMerge(tagNumber));
911 case Builder._OPTIONAL_SINT64:
912 return input.readSint64().chain(assignAndMerge(tagNumber));
913 case Builder._OPTIONAL_UINT32:
914 return input.readUint32().chain(assignAndMerge(tagNumber));
915 case Builder._OPTIONAL_UINT64:
916 return input.readUint64().chain(assignAndMerge(tagNumber));
917 case Builder._OPTIONAL_FIXED32:
918 return input.readFixed32().chain(assignAndMerge(tagNumber));
919 case Builder._OPTIONAL_FIXED64:
920 return input.readFixed64().chain(assignAndMerge(tagNumber));
921 case Builder._OPTIONAL_SFIXED32:
922 return input.readSfixed32().chain(assignAndMerge(tagNumber));
923 case Builder._OPTIONAL_SFIXED64:
924 return input.readSfixed64().chain(assignAndMerge(tagNumber));
925 case Builder._OPTIONAL_MESSAGE:
926 Builder subBuilder = info_.subBuilder(tagNumber)();
927 if (_fieldValues.containsKey(tagNumber)) {
928 subBuilder.mergeFromMessage(getField(tagNumber));
929 }
930 return input.readMessage(subBuilder, extensionRegistry).chain((_) {
931 _fieldValues[tagNumber] = subBuilder.buildPartial();
932 return merge();
933 });
934 case Builder._REPEATED_BOOL:
935 return readPackable(wireType, tagNumber, input.readBool);
936 case Builder._REPEATED_BYTES:
937 return input.readBytes().chain(appendAndMerge(tagNumber));
938 case Builder._REPEATED_STRING:
939 return input.readString().chain(appendAndMerge(tagNumber));
940 case Builder._REPEATED_FLOAT:
941 return readPackable(wireType, tagNumber, input.readFloat);
942 case Builder._REPEATED_DOUBLE:
943 return readPackable(wireType, tagNumber, input.readDouble);
944 case Builder._REPEATED_ENUM:
945 return readPackableIoc(wireType, tagNumber, (var assigner) =>
946 input.readEnum().transform((int rawValue) {
947 var value =
948 _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
949 if (value == null) {
950 unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
951 } else {
952 assigner(value);
953 }
954 return null;
955 })
956 );
957 case Builder._REPEATED_GROUP:
958 Builder subBuilder = info_.subBuilder(tagNumber)();
959 return input.readGroup(tagNumber, subBuilder, extensionRegistry)
960 .chain((_) {
961 List list = getField(tagNumber);
962 list.add(subBuilder.buildPartial());
963 return merge();
964 });
965 case Builder._REPEATED_INT32:
966 return readPackable(wireType, tagNumber, input.readInt32);
967 case Builder._REPEATED_INT64:
968 return readPackable(wireType, tagNumber, input.readInt64);
969 case Builder._REPEATED_SINT32:
970 return readPackable(wireType, tagNumber, input.readSint32);
971 case Builder._REPEATED_SINT64:
972 return readPackable(wireType, tagNumber, input.readSint64);
973 case Builder._REPEATED_UINT32:
974 return readPackable(wireType, tagNumber, input.readUint32);
975 case Builder._REPEATED_UINT64:
976 return readPackable(wireType, tagNumber, input.readUint64);
977 case Builder._REPEATED_FIXED32:
978 return readPackable(wireType, tagNumber, input.readFixed32);
979 case Builder._REPEATED_FIXED64:
980 return readPackable(wireType, tagNumber, input.readFixed64);
981 case Builder._REPEATED_SFIXED32:
982 return readPackable(wireType, tagNumber, input.readSfixed32);
983 case Builder._REPEATED_SFIXED64:
984 return readPackable(wireType, tagNumber, input.readSfixed64);
985 case Builder._REPEATED_MESSAGE:
986 Builder subBuilder = info_.subBuilder(tagNumber)();
987 return input.readMessage(subBuilder, extensionRegistry).chain((_) {
988 List list = getField(tagNumber);
989 list.add(subBuilder.buildPartial());
990 return merge();
991 });
992 default:
993 throw "Unknown field type $fieldType";
994 }
995 };
996
997 Future mergeImpl() {
998 return input.readTag().chain((int tag) {
999 if (tag == 0) {
1000 unknownFields = unknownFieldSetBuilder.build();
1001 onChanged();
1002 return new Future.immediate(null);
1003 }
1004 int wireType = tag & 0x7;
1005 int tagNumber = tag >> 3;
1006 int fieldType = -1;
1007
1008 if (info_.containsTagNumber(tagNumber)) {
1009 fieldType = info_.fieldType(tagNumber);
1010 } else {
1011 Extension extension =
1012 extensionRegistry.getExtension(info_.messageName, tagNumber);
1013 if (extension != null) {
1014 _addExtensionToMap(extension);
1015 fieldType = extension.type;
1016 }
1017 }
1018 if (fieldType == -1 || !wireTypeMatch(tagNumber, fieldType, wireType)) {
1019 return parseUnknownFieldFromStream(input, unknownFieldSetBuilder,
1020 extensionRegistry, tag).chain(_(bool unknownTag) {
1021 if (!unknownTag) {
1022 unknownFields = unknownFieldSetBuilder.build();
1023 onChanged();
1024 return new Future.immediate(null);
1025 } else {
1026 return merge();
1027 }
1028 });
1029 }
1030 return readField(tagNumber, wireType, fieldType);
1031 });
1032 };
1033 merge = mergeImpl;
1034 return merge().transform((_) => this);
1035 }
1036
1037 Future<Builder> mergeFromStream(InputStream input,
1038 [ExtensionRegistry extensionRegistry]) {
1039 extensionRegistry = extensionRegistry == null ?
1040 ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
1041 CodedStreamReader codedInput = new CodedStreamReader(input);
1042 return mergeFromCodedStreamReader(codedInput, extensionRegistry)
1043 .transform((_) {
1044 codedInput.checkLastTagWas(0);
1045 return this;
1046 });
1047 }
1048
1049 Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
1050 _unknownFields =
1051 (new UnknownFieldSet_Builder(_unknownFields))
1052 .mergeFromUnknownFieldSet(unknownFields).build();
1053 onChanged();
1054 return this;
1055 }
1056
1057 void onBuilt() {
1058 // if (builderParent !== null) {
1059 // markClean();
1060 // }
1061 }
1062
1063 void onChanged() {
1064 // if (_isClean && builderParent !== null) {
1065 // builderParent.markDirty();
1066 //
1067 // // Don't keep dispatching invalidations until build is called again.
1068 // _isClean = false;
1069 // }
1070 }
1071
1072 bool parseUnknownFieldFromBuffer(CodedBufferReader input,
1073 UnknownFieldSet_Builder unknownFieldSetBuilder, int tag) {
1074 // If returns false, the tag is an "end group" which is expected
1075 // If returns true, the field is considered unknown.
1076 bool val = unknownFieldSetBuilder.mergeFieldFromBuffer(tag, input);
1077 return val;
1078 }
1079
1080 Future<bool> parseUnknownFieldFromStream(CodedStreamReader input,
1081 UnknownFieldSet_Builder unknownFieldSetBuilder,
1082 ExtensionRegistry extensionRegistry, int tag) {
1083 // If returns false, the tag is an "end group" which is expected
1084 // If returns true, the field is considered unknown.
1085 return unknownFieldSetBuilder.mergeFieldFromStream(tag, input);
1086 }
1087
1088 Message partial(GeneratedMessage result) {
1089 // Set empty repeating fields
1090 info_.fieldInfo.forEach(
1091 void _(int tagNumber, FieldInfo fieldInfo){
1092 int type = fieldInfo.type;
1093 if ((type & _REPEATED_BIT) != 0 && !hasField(tagNumber)) {
1094 result._fieldValues[tagNumber] = PbImmutableList.EMPTY;
1095 }
1096 }
1097 );
1098
1099 // Copy extensions
1100 if (_extensions != null) {
1101 for (int tagNumber in _extensions.getKeys()) {
1102 if (result._extensions == null) {
1103 result._extensions = new Map<int, Extension>();
1104 }
1105 result._extensions[tagNumber] = _extensions[tagNumber];
1106 }
1107 }
1108
1109 // Then copy fields that have been set
1110 for (int tagNumber in _fieldValues.getKeys()) {
1111 if (hasField(tagNumber)) {
1112 int type = _getFieldType(tagNumber);
1113 result._fieldValues[tagNumber] =
1114 _converterForType(type)(_fieldValues[tagNumber]);
1115 }
1116 }
1117
1118 onBuilt();
1119 return result;
1120 }
1121
1122 // Shorthand for setField
1123 void s_(int tagNumber, Object value) {
1124 setField(tagNumber, value);
1125 }
1126
1127 /**
1128 * Set the value of a non-repeated extension field.
1129 */
1130 void setExtension(Extension extension, var value) {
1131 _checkExtension(extension);
1132 _addExtensionToMap(extension);
1133 setField(extension.tagNumber, value, extension.type);
1134 }
1135
1136 /**
1137 * Sets the value of a given field by its [tagNumber]. Can throw an
1138 * [:IllegalArgumentException:] if the value does not match the type
1139 * associated with [tagNumber].
1140 */
1141 void setField(int tagNumber, var value, [int fieldType = null]) {
1142 if (value == null) {
1143 throw new NullPointerException();
1144 }
1145 if (fieldType == null) {
1146 if (!info_.containsTagNumber(tagNumber)) {
1147 throw new IllegalArgumentException("Unknown tag: $tagNumber");
1148 }
1149 fieldType = info_.fieldType(tagNumber);
1150 }
1151 if ((fieldType & _REPEATED_BIT) != 0) {
1152 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1153 "repeating field (use get + .add())"));
1154 }
1155
1156 // Validate type and range
1157 value = _validate(tagNumber, fieldType & ~0x7, value);
1158 _fieldValues[tagNumber] = value;
1159 onChanged();
1160 }
1161
1162 UnknownFieldSet get unknownFields() => _unknownFields;
1163
1164 void set unknownFields(UnknownFieldSet unknownFields) {
1165 _unknownFields = unknownFields;
1166 onChanged();
1167 }
1168
1169 void _addExtensionToMap(Extension extension) {
1170 if (_extensions == null) {
1171 _extensions = new Map<int, Extension>();
1172 }
1173 _extensions[extension.tagNumber] = extension;
1174 }
1175
1176 void _checkExtension(Extension extension) {
1177 if (extension.extendee != info_.messageName) {
1178 throw new IllegalArgumentException(
1179 "Extension $extension not legal for message ${info_.messageName}");
1180 }
1181 }
1182
1183 // dart2js's implementation of 'x is int' is not reliable
1184 bool _isInt(var value) {
1185 return (value is num) && (value == value.floor());
1186 }
1187
1188 // Extract a value from its JSON representation
1189 Dynamic _convertJsonValue(var value, int tagNumber, int fieldType,
1190 ExtensionRegistry extensionRegistry) {
1191 // Mask off 'required', 'repeated' and 'packed' bits to obtain base type
1192 fieldType &= ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT);
1193
1194 String expectedType; // for exception message
1195 switch (fieldType) {
1196 case _BOOL_BIT:
1197 if (value is bool) {
1198 return value;
1199 } else if (value is String) {
1200 if (value == "true") {
1201 return true;
1202 } else if (value == "false") {
1203 return false;
1204 }
1205 }
1206 expectedType = 'bool, "true", or "false"';
1207 break;
1208 case _BYTES_BIT:
1209 if (value is String) {
1210 return Base64Codec.defaultInstance.decodeAsList(value);
1211 }
1212 expectedType = 'Base64 String';
1213 break;
1214 case _STRING_BIT:
1215 if (value is String) {
1216 return value;
1217 }
1218 expectedType = "String";
1219 break;
1220 case _FLOAT_BIT:
1221 case _DOUBLE_BIT:
1222 // Allow quoted values, although we don't emit them
1223 if (value is double) {
1224 return value;
1225 } else if (value is num) {
1226 return value.toDouble();
1227 } else if (value is String) {
1228 return Math.parseDouble(value);
1229 }
1230 expectedType = "num or stringified num";
1231 break;
1232 case _ENUM_BIT:
1233 // Allow quoted values, although we don't emit them
1234 if (value is String) {
1235 value = Math.parseInt(value);
1236 }
1237 if (_isInt(value)) {
1238 return _getValueOfFunc(tagNumber, extensionRegistry)(value.toInt());
1239 }
1240 expectedType = "int or stringified int";
1241 break;
1242 case _INT32_BIT:
1243 case _SINT32_BIT:
1244 case _UINT32_BIT:
1245 case _FIXED32_BIT:
1246 case _SFIXED32_BIT:
1247 // Allow quoted values, although we don't emit them
1248 if (_isInt(value)) {
1249 return value.toInt();
1250 } else if (value is String) {
1251 return Math.parseInt(value);
1252 }
1253 expectedType = "int or stringified int";
1254 break;
1255 case _INT64_BIT:
1256 case _SINT64_BIT:
1257 case _UINT64_BIT:
1258 case _FIXED64_BIT:
1259 case _SFIXED64_BIT:
1260 // Allow unquoted values, although we don't emit them
1261 // TODO - decode large numbers as Packed64 on JavaScript platforms
1262 if (value is String) {
1263 return Math.parseInt(value);
1264 } else if (_isInt(value)) {
1265 return value.toInt();
1266 }
1267 expectedType = "int or stringified int";
1268 break;
1269 case _GROUP_BIT:
1270 case _MESSAGE_BIT:
1271 if (value is Map<String, Object>) {
1272 Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
1273 subBuilder._mergeFromJson(value, extensionRegistry);
1274 return subBuilder.build();
1275 }
1276 expectedType = "nested message or group";
1277 break;
1278 default:
1279 throw new PbException("Unknown type $fieldType");
1280 }
1281 throw new PbException("Expected type $expectedType, got $value");
1282 }
1283
1284 void _findInvalidFields(List<String> invalidFields) {
1285 info_._findInvalidFields(_fieldValues, invalidFields);
1286 invalidFields.sort((a, b) => a.compareTo(b));
1287 }
1288
1289 /**
1290 * Returns the type associated with a given tag number, either from the
1291 * [BuilderInfo] associated with this [Builder], or from a known extension.
1292 * If the type is unknown, [null] is returned.
1293 */
1294 int _getFieldType(int tagNumber) {
1295 int type = info_.fieldType(tagNumber);
1296 if (type == null && _extensions != null &&
1297 _extensions.containsKey(tagNumber)) {
1298 type = _extensions[tagNumber].type;
1299 }
1300 return type;
1301 }
1302
1303 Builder _getSubBuilder(int tagNumber, ExtensionRegistry extensionRegistry) {
1304 CreateBuilderFunc subBuilderFunc = info_.subBuilder(tagNumber);
1305 if (subBuilderFunc == null && extensionRegistry != null) {
1306 subBuilderFunc = extensionRegistry.getExtension(info_.messageName,
1307 tagNumber).subBuilder;
1308 }
1309 if (subBuilderFunc == null) {
1310 throw new PbException("No subbuilder for tag $tagNumber");
1311 }
1312 return subBuilderFunc();
1313 }
1314
1315 ValueOfFunc _getValueOfFunc(int tagNumber,
1316 ExtensionRegistry extensionRegistry) {
1317 ValueOfFunc valueOfFunc = info_.valueOfFunc(tagNumber);
1318 if (valueOfFunc == null && extensionRegistry != null) {
1319 valueOfFunc = extensionRegistry.getExtension(info_.messageName,
1320 tagNumber).valueOf;
1321 }
1322 if (valueOfFunc == null) {
1323 throw new PbException("No valueOf for tag $tagNumber");
1324 }
1325 return valueOfFunc;
1326 }
1327
1328 // Merge fields from a previously decoded JSON object
1329 Builder _mergeFromJson(Map<String, Object> json,
1330 ExtensionRegistry extensionRegistry) {
1331 List<int> tags = new List<int>.from(
1332 json.getKeys().map((x) => Math.parseInt(x)));
1333 tags.sort((a, b) => a.compareTo(b));
1334
1335 for (int tagNumber in tags) {
1336 var fieldValue = json[tagNumber.toString()];
1337 int fieldType = -1;
1338
1339 Extension extension = null;
1340 if (info_.containsTagNumber(tagNumber)) {
1341 fieldType = info_.fieldType(tagNumber);
1342 } else if (extensionRegistry != null) {
1343 extension = extensionRegistry.getExtension(info_.messageName,
1344 tagNumber);
1345 if (extension == null) {
1346 // Unknown extensions can be skipped.
1347 continue;
1348 }
1349 _addExtensionToMap(extension);
1350 fieldType = extension.type;
1351 }
1352 if (fieldType == -1) {
1353 throw new PbException("Unknown field type for tag number $tagNumber");
1354 }
1355 if ((fieldType & _REPEATED_BIT) != 0) {
1356 List thisList = getField(tagNumber);
1357 if (thisList == null) {
1358 thisList = extension.makeDefault();
1359 }
1360 for (var value in fieldValue) {
1361 value = _convertJsonValue(value, tagNumber, fieldType,
1362 extensionRegistry);
1363 thisList.add(value);
1364 }
1365 _fieldValues[tagNumber] = thisList;
1366 onChanged();
1367 } else {
1368 var value = _convertJsonValue(fieldValue, tagNumber, fieldType,
1369 extensionRegistry);
1370 setField(tagNumber, value, fieldType);
1371 }
1372 }
1373 }
1374
1375 // does not perform validation
1376 void _setExtension(Extension extension, var value) {
1377 _addExtensionToMap(extension);
1378 _fieldValues[extension.tagNumber] = value;
1379 }
1380
1381 String _generateMessage(int tagNumber, var value, String detail) {
1382 String fieldName;
1383 if (_extensions != null && _extensions[tagNumber] != null) {
1384 fieldName = _extensions[tagNumber].name;
1385 } else {
1386 fieldName = info_.fieldName(tagNumber);
1387 }
1388 String messageType = info_.messageName;
1389 return "Illegal to set field $fieldName ($tagNumber) of $messageType"
1390 " to value ($value): $detail";
1391 }
1392
1393 // For int values, force coercion to int since there isn't a reliable
1394 // check for int-ness that works in both the VM and dart2js
1395 Dynamic _validate(int tagNumber, int fieldType, var value) {
1396 switch (fieldType) {
1397 case _BOOL_BIT:
1398 if (value is !bool) {
1399 throw new IllegalArgumentException(
1400 _generateMessage(tagNumber, value, "not type bool"));
1401 }
1402 break;
1403 case _BYTES_BIT:
1404 if (value is !List<int>) {
1405 throw new IllegalArgumentException(
1406 _generateMessage(tagNumber, value, "not List<int>"));
1407 }
1408 break;
1409 case _STRING_BIT:
1410 if (value is !String) {
1411 throw new IllegalArgumentException(
1412 _generateMessage(tagNumber, value, "not type String"));
1413 }
1414 break;
1415 case _FLOAT_BIT:
1416 if (value is !double) {
1417 throw new IllegalArgumentException(
1418 _generateMessage(tagNumber, value, "not type double"));
1419 }
1420 if (value < -_Constants.MAX_FLOAT || value > _Constants.MAX_FLOAT) {
1421 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1422 "out of range for float"));
1423 }
1424 break;
1425 case _DOUBLE_BIT:
1426 if (value is !double) {
1427 throw new IllegalArgumentException(
1428 _generateMessage(tagNumber, value, "not type double"));
1429 }
1430 break;
1431 case _ENUM_BIT:
1432 if (value is !ProtobufEnum) {
1433 throw new IllegalArgumentException(
1434 _generateMessage(tagNumber, value, "not type ProtobufEnum"));
1435 }
1436 break;
1437 case _INT32_BIT:
1438 if (!_isInt(value)) {
1439 throw new IllegalArgumentException(
1440 _generateMessage(tagNumber, value, "not type int"));
1441 }
1442 if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
1443 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1444 "out of range for int32"));
1445 }
1446 value = value.toInt();
1447 break;
1448 case _INT64_BIT:
1449 if (!_isInt(value) && value is !Packed64) {
1450 throw new IllegalArgumentException(
1451 _generateMessage(tagNumber, value, "not int or Packed64"));
1452 }
1453 if (_isInt(value) &&
1454 (value < _Constants.MIN_SINT64 || value > _Constants.MAX_SINT64)) {
1455 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1456 "out of range for int64"));
1457 }
1458 if (value is !Packed64) {
1459 value = value.toInt();
1460 }
1461 break;
1462 case _SINT32_BIT:
1463 if (!_isInt(value)) {
1464 throw new IllegalArgumentException(
1465 _generateMessage(tagNumber, value, "not type int"));
1466 }
1467 if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
1468 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1469 "out of range for sint32"));
1470 }
1471 value = value.toInt();
1472 break;
1473 case _SINT64_BIT:
1474 if (!_isInt(value) && value is !Packed64) {
1475 throw new IllegalArgumentException(
1476 _generateMessage(tagNumber, value, "not int or Packed64"));
1477 }
1478 if (_isInt(value) &&
1479 (value < _Constants.MIN_SINT64 || value > _Constants.MAX_SINT64)) {
1480 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1481 "out of range for sint64"));
1482 }
1483 if (value is !Packed64) {
1484 value = value.toInt();
1485 }
1486 break;
1487 case _UINT32_BIT:
1488 if (!_isInt(value)) {
1489 throw new IllegalArgumentException(
1490 _generateMessage(tagNumber, value, "not type int"));
1491 }
1492 if (value < 0 || value > _Constants.MAX_UINT32) {
1493 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1494 "out of range for uint32"));
1495 }
1496 value = value.toInt();
1497 break;
1498 case _UINT64_BIT:
1499 if (!_isInt(value) && value is !Packed64) {
1500 throw new IllegalArgumentException(
1501 _generateMessage(tagNumber, value, "not int or Packed64"));
1502 }
1503 if ((_isInt(value)) && (value < 0 || value > _Constants.MAX_UINT64)) {
1504 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1505 "out of range for uint64"));
1506 }
1507 if (value is !Packed64) {
1508 value = value.toInt();
1509 }
1510 break;
1511 case _FIXED32_BIT:
1512 if (!_isInt(value)) {
1513 throw new IllegalArgumentException(
1514 _generateMessage(tagNumber, value, "not type int"));
1515 }
1516 if (value < 0 || value > _Constants.MAX_UINT32) {
1517 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1518 "out of range for fixed32"));
1519 }
1520 break;
1521 case _FIXED64_BIT:
1522 if (!_isInt(value) && value is !Packed64) {
1523 throw new IllegalArgumentException(
1524 _generateMessage(tagNumber, value, "not int or Packed64"));
1525 }
1526 if ((_isInt(value)) && (value < 0 || value > _Constants.MAX_UINT64)) {
1527 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1528 "out of range for fixed64"));
1529 }
1530 if (value is !Packed64) {
1531 value = value.toInt();
1532 }
1533 break;
1534 case _SFIXED32_BIT:
1535 if (!_isInt(value)) {
1536 throw new IllegalArgumentException(
1537 _generateMessage(tagNumber, value, "not type int"));
1538 }
1539 if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
1540 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1541 "out of range for sfixed32"));
1542 }
1543 break;
1544 case _SFIXED64_BIT:
1545 if (!_isInt(value) && value is !Packed64) {
1546 throw new IllegalArgumentException(
1547 _generateMessage(tagNumber, value, "not int or Packed64"));
1548 }
1549 if ((_isInt(value)) && (value < _Constants.MIN_SINT64 ||
1550 value > _Constants.MAX_SINT64)) {
1551 throw new IllegalArgumentException(_generateMessage(tagNumber, value,
1552 "out of range for sfixed64"));
1553 }
1554 if (value is !Packed64) {
1555 value = value.toInt();
1556 }
1557 break;
1558 case _GROUP_BIT:
1559 case _MESSAGE_BIT:
1560 if (value is !GeneratedMessage) {
1561 throw new IllegalArgumentException(
1562 _generateMessage(tagNumber, value, "not a GeneratedMessage"));
1563 }
1564 break;
1565 default:
1566 throw new IllegalArgumentException(
1567 _generateMessage(tagNumber, value, "field has unknown type "
1568 "$fieldType"));
1569 }
1570 return value;
1571 }
1572 }
OLDNEW
« no previous file with comments | « lib/protobuf/plugin/protoc/plugin.pb.dart ('k') | lib/protobuf/runtime/BuilderInfo.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698