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

Unified 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, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/protobuf/plugin/protoc/plugin.pb.dart ('k') | lib/protobuf/runtime/BuilderInfo.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/protobuf/runtime/Builder.dart
diff --git a/lib/protobuf/runtime/Builder.dart b/lib/protobuf/runtime/Builder.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d89f706d5cd97b3fb7bf2d832d7461f8b53fd0a5
--- /dev/null
+++ b/lib/protobuf/runtime/Builder.dart
@@ -0,0 +1,1572 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+typedef Builder CreateBuilderFunc();
+typedef Object MakeDefaultFunc();
+typedef ProtobufEnum ValueOfFunc(int value);
+
+class Builder implements ChangeListener {
+ static final int _REQUIRED_BIT = 0x1;
+ static final int _REPEATED_BIT = 0x2;
+ static final int _PACKED_BIT = 0x4;
+
+ static final int _BOOL_BIT = 0x10;
+ static final int _BYTES_BIT = 0x20;
+ static final int _STRING_BIT = 0x40;
+ static final int _DOUBLE_BIT = 0x80;
+ static final int _FLOAT_BIT = 0x100;
+ static final int _ENUM_BIT = 0x200;
+ static final int _GROUP_BIT = 0x400;
+ static final int _INT32_BIT = 0x800;
+ static final int _INT64_BIT = 0x1000;
+ static final int _SINT32_BIT = 0x2000;
+ static final int _SINT64_BIT = 0x4000;
+ static final int _UINT32_BIT = 0x8000;
+ static final int _UINT64_BIT = 0x10000;
+ static final int _FIXED32_BIT = 0x20000;
+ static final int _FIXED64_BIT = 0x40000;
+ static final int _SFIXED32_BIT = 0x80000;
+ static final int _SFIXED64_BIT = 0x100000;
+ static final int _MESSAGE_BIT = 0x200000;
+
+ static final int _OPTIONAL_BOOL = _BOOL_BIT;
+ static final int _OPTIONAL_BYTES = _BYTES_BIT;
+ static final int _OPTIONAL_STRING = _STRING_BIT;
+ static final int _OPTIONAL_FLOAT = _FLOAT_BIT;
+ static final int _OPTIONAL_DOUBLE = _DOUBLE_BIT;
+ static final int _OPTIONAL_ENUM = _ENUM_BIT;
+ static final int _OPTIONAL_GROUP = _GROUP_BIT;
+ static final int _OPTIONAL_INT32 = _INT32_BIT;
+ static final int _OPTIONAL_INT64 = _INT64_BIT;
+ static final int _OPTIONAL_SINT32 = _SINT32_BIT;
+ static final int _OPTIONAL_SINT64 = _SINT64_BIT;
+ static final int _OPTIONAL_UINT32 = _UINT32_BIT;
+ static final int _OPTIONAL_UINT64 = _UINT64_BIT;
+ static final int _OPTIONAL_FIXED32 = _FIXED32_BIT;
+ static final int _OPTIONAL_FIXED64 = _FIXED64_BIT;
+ static final int _OPTIONAL_SFIXED32 = _SFIXED32_BIT;
+ static final int _OPTIONAL_SFIXED64 = _SFIXED64_BIT;
+ static final int _OPTIONAL_MESSAGE = _MESSAGE_BIT;
+
+ static final int _REQUIRED_BOOL = _REQUIRED_BIT | _BOOL_BIT;
+ static final int _REQUIRED_BYTES = _REQUIRED_BIT | _BYTES_BIT;
+ static final int _REQUIRED_STRING = _REQUIRED_BIT | _STRING_BIT;
+ static final int _REQUIRED_FLOAT = _REQUIRED_BIT | _FLOAT_BIT;
+ static final int _REQUIRED_DOUBLE = _REQUIRED_BIT | _DOUBLE_BIT;
+ static final int _REQUIRED_ENUM = _REQUIRED_BIT | _ENUM_BIT;
+ static final int _REQUIRED_GROUP = _REQUIRED_BIT | _GROUP_BIT;
+ static final int _REQUIRED_INT32 = _REQUIRED_BIT | _INT32_BIT;
+ static final int _REQUIRED_INT64 = _REQUIRED_BIT | _INT64_BIT;
+ static final int _REQUIRED_SINT32 = _REQUIRED_BIT | _SINT32_BIT;
+ static final int _REQUIRED_SINT64 = _REQUIRED_BIT | _SINT64_BIT;
+ static final int _REQUIRED_UINT32 = _REQUIRED_BIT | _UINT32_BIT;
+ static final int _REQUIRED_UINT64 = _REQUIRED_BIT | _UINT64_BIT;
+ static final int _REQUIRED_FIXED32 = _REQUIRED_BIT | _FIXED32_BIT;
+ static final int _REQUIRED_FIXED64 = _REQUIRED_BIT | _FIXED64_BIT;
+ static final int _REQUIRED_SFIXED32 = _REQUIRED_BIT | _SFIXED32_BIT;
+ static final int _REQUIRED_SFIXED64 = _REQUIRED_BIT | _SFIXED64_BIT;
+ static final int _REQUIRED_MESSAGE = _REQUIRED_BIT | _MESSAGE_BIT;
+
+ static final int _REPEATED_BOOL = _REPEATED_BIT | _BOOL_BIT;
+ static final int _REPEATED_BYTES = _REPEATED_BIT | _BYTES_BIT;
+ static final int _REPEATED_STRING = _REPEATED_BIT | _STRING_BIT;
+ static final int _REPEATED_FLOAT = _REPEATED_BIT | _FLOAT_BIT;
+ static final int _REPEATED_DOUBLE = _REPEATED_BIT | _DOUBLE_BIT;
+ static final int _REPEATED_ENUM = _REPEATED_BIT | _ENUM_BIT;
+ static final int _REPEATED_GROUP = _REPEATED_BIT | _GROUP_BIT;
+ static final int _REPEATED_INT32 = _REPEATED_BIT | _INT32_BIT;
+ static final int _REPEATED_INT64 = _REPEATED_BIT | _INT64_BIT;
+ static final int _REPEATED_SINT32 = _REPEATED_BIT | _SINT32_BIT;
+ static final int _REPEATED_SINT64 = _REPEATED_BIT | _SINT64_BIT;
+ static final int _REPEATED_UINT32 = _REPEATED_BIT | _UINT32_BIT;
+ static final int _REPEATED_UINT64 = _REPEATED_BIT | _UINT64_BIT;
+ static final int _REPEATED_FIXED32 = _REPEATED_BIT | _FIXED32_BIT;
+ static final int _REPEATED_FIXED64 = _REPEATED_BIT | _FIXED64_BIT;
+ static final int _REPEATED_SFIXED32 = _REPEATED_BIT | _SFIXED32_BIT;
+ static final int _REPEATED_SFIXED64 = _REPEATED_BIT | _SFIXED64_BIT;
+ static final int _REPEATED_MESSAGE = _REPEATED_BIT | _MESSAGE_BIT;
+
+ static final int _PACKED_BOOL = _REPEATED_BIT | _PACKED_BIT | _BOOL_BIT;
+ static final int _PACKED_FLOAT = _REPEATED_BIT | _PACKED_BIT | _FLOAT_BIT;
+ static final int _PACKED_DOUBLE = _REPEATED_BIT | _PACKED_BIT | _DOUBLE_BIT;
+ static final int _PACKED_ENUM = _REPEATED_BIT | _PACKED_BIT | _ENUM_BIT;
+ static final int _PACKED_INT32 = _REPEATED_BIT | _PACKED_BIT | _INT32_BIT;
+ static final int _PACKED_INT64 = _REPEATED_BIT | _PACKED_BIT | _INT64_BIT;
+ static final int _PACKED_SINT32 = _REPEATED_BIT | _PACKED_BIT | _SINT32_BIT;
+ static final int _PACKED_SINT64 = _REPEATED_BIT | _PACKED_BIT | _SINT64_BIT;
+ static final int _PACKED_UINT32 = _REPEATED_BIT | _PACKED_BIT | _UINT32_BIT;
+ static final int _PACKED_UINT64 = _REPEATED_BIT | _PACKED_BIT | _UINT64_BIT;
+ static final int _PACKED_FIXED32 = _REPEATED_BIT | _PACKED_BIT | _FIXED32_BIT;
+ static final int _PACKED_FIXED64 = _REPEATED_BIT | _PACKED_BIT | _FIXED64_BIT;
+ static final int _PACKED_SFIXED32 = _REPEATED_BIT | _PACKED_BIT |
+ _SFIXED32_BIT;
+ static final int _PACKED_SFIXED64 = _REPEATED_BIT | _PACKED_BIT |
+ _SFIXED64_BIT;
+
+ // Short names for use in generated code
+
+ // _O_ptional
+ static final int OB = _OPTIONAL_BOOL;
+ static final int OY = _OPTIONAL_BYTES;
+ static final int OS = _OPTIONAL_STRING;
+ static final int OF = _OPTIONAL_FLOAT;
+ static final int OD = _OPTIONAL_DOUBLE;
+ static final int OE = _OPTIONAL_ENUM;
+ static final int OG = _OPTIONAL_GROUP;
+ static final int O3 = _OPTIONAL_INT32;
+ static final int O6 = _OPTIONAL_INT64;
+ static final int OS3 = _OPTIONAL_SINT32;
+ static final int OS6 = _OPTIONAL_SINT64;
+ static final int OU3 = _OPTIONAL_UINT32;
+ static final int OU6 = _OPTIONAL_UINT64;
+ static final int OF3 = _OPTIONAL_FIXED32;
+ static final int OF6 = _OPTIONAL_FIXED64;
+ static final int OSF3 = _OPTIONAL_SFIXED32;
+ static final int OSF6 = _OPTIONAL_SFIXED64;
+ static final int OM = _OPTIONAL_MESSAGE;
+
+ // re_Q_uired
+ static final int QB = _REQUIRED_BOOL;
+ static final int QY = _REQUIRED_BYTES;
+ static final int QS = _REQUIRED_STRING;
+ static final int QF = _REQUIRED_FLOAT;
+ static final int QD = _REQUIRED_DOUBLE;
+ static final int QE = _REQUIRED_ENUM;
+ static final int QG = _REQUIRED_GROUP;
+ static final int Q3 = _REQUIRED_INT32;
+ static final int Q6 = _REQUIRED_INT64;
+ static final int QS3 = _REQUIRED_SINT32;
+ static final int QS6 = _REQUIRED_SINT64;
+ static final int QU3 = _REQUIRED_UINT32;
+ static final int QU6 = _REQUIRED_UINT64;
+ static final int QF3 = _REQUIRED_FIXED32;
+ static final int QF6 = _REQUIRED_FIXED64;
+ static final int QSF3 = _REQUIRED_SFIXED32;
+ static final int QSF6 = _REQUIRED_SFIXED64;
+ static final int QM = _REQUIRED_MESSAGE;
+
+ // re_P_eated
+ static final int PB = _REPEATED_BOOL;
+ static final int PY = _REPEATED_BYTES;
+ static final int PS = _REPEATED_STRING;
+ static final int PF = _REPEATED_FLOAT;
+ static final int PD = _REPEATED_DOUBLE;
+ static final int PE = _REPEATED_ENUM;
+ static final int PG = _REPEATED_GROUP;
+ static final int P3 = _REPEATED_INT32;
+ static final int P6 = _REPEATED_INT64;
+ static final int PS3 = _REPEATED_SINT32;
+ static final int PS6 = _REPEATED_SINT64;
+ static final int PU3 = _REPEATED_UINT32;
+ static final int PU6 = _REPEATED_UINT64;
+ static final int PF3 = _REPEATED_FIXED32;
+ static final int PF6 = _REPEATED_FIXED64;
+ static final int PSF3 = _REPEATED_SFIXED32;
+ static final int PSF6 = _REPEATED_SFIXED64;
+ static final int PM = _REPEATED_MESSAGE;
+
+ // pac_K_ed
+ static final int KB = _PACKED_BOOL;
+ static final int KE = _PACKED_ENUM;
+ static final int KF = _PACKED_FLOAT;
+ static final int KD = _PACKED_DOUBLE;
+ static final int K3 = _PACKED_INT32;
+ static final int K6 = _PACKED_INT64;
+ static final int KS3 = _PACKED_SINT32;
+ static final int KS6 = _PACKED_SINT64;
+ static final int KU3 = _PACKED_UINT32;
+ static final int KU6 = _PACKED_UINT64;
+ static final int KF3 = _PACKED_FIXED32;
+ static final int KF6 = _PACKED_FIXED64;
+ static final int KSF3 = _PACKED_SFIXED32;
+ static final int KSF6 = _PACKED_SFIXED64;
+
+ // Closures commonly used by initializers
+ static MakeDefaultFunc __STRING_EMPTY; // () => ''
+ static MakeDefaultFunc __BYTES_EMPTY; // () => <int>[]
+ static MakeDefaultFunc __BOOL_FALSE; // () => false
+ static MakeDefaultFunc __INT_ZERO; // () => 0
+ static MakeDefaultFunc __DOUBLE_ZERO; // () => 0.0
+
+ static MakeDefaultFunc get _STRING_EMPTY() {
+ if (__STRING_EMPTY === null) {
+ __STRING_EMPTY = () => '';
+ }
+ return __STRING_EMPTY;
+ }
+
+ static MakeDefaultFunc get _BYTES_EMPTY() {
+ if (__BYTES_EMPTY === null) {
+ __BYTES_EMPTY = () => <int>[];
+ }
+ return __BYTES_EMPTY;
+ }
+
+ static MakeDefaultFunc get _BOOL_FALSE() {
+ if (__BOOL_FALSE === null) {
+ __BOOL_FALSE = () => false;
+ }
+ return __BOOL_FALSE;
+ }
+
+ static MakeDefaultFunc get _INT_ZERO() {
+ if (__INT_ZERO === null) {
+ __INT_ZERO = () => 0;
+ }
+ return __INT_ZERO;
+ }
+
+ static MakeDefaultFunc get _DOUBLE_ZERO() {
+ if (__DOUBLE_ZERO === null) {
+ __DOUBLE_ZERO = () => 0.0;
+ }
+ return __DOUBLE_ZERO;
+ }
+
+ static MakeDefaultFunc _defaultForType(int type) {
+ switch (type) {
+ case _OPTIONAL_BOOL: case _REQUIRED_BOOL:
+ return _BOOL_FALSE;
+ case _OPTIONAL_BYTES: case _REQUIRED_BYTES:
+ return _BYTES_EMPTY;
+ case _OPTIONAL_STRING: case _REQUIRED_STRING:
+ return _STRING_EMPTY;
+ case _OPTIONAL_FLOAT: case _REQUIRED_FLOAT:
+ case _OPTIONAL_DOUBLE: case _REQUIRED_DOUBLE:
+ return _DOUBLE_ZERO;
+ case _OPTIONAL_INT32: case _REQUIRED_INT32:
+ case _OPTIONAL_INT64: case _REQUIRED_INT64:
+ case _OPTIONAL_SINT32: case _REQUIRED_SINT32:
+ case _OPTIONAL_SINT64: case _REQUIRED_SINT64:
+ case _OPTIONAL_UINT32: case _REQUIRED_UINT32:
+ case _OPTIONAL_UINT64: case _REQUIRED_UINT64:
+ case _OPTIONAL_FIXED32: case _REQUIRED_FIXED32:
+ case _OPTIONAL_FIXED64: case _REQUIRED_FIXED64:
+ case _OPTIONAL_SFIXED32: case _REQUIRED_SFIXED32:
+ case _OPTIONAL_SFIXED64: case _REQUIRED_SFIXED64:
+ return _INT_ZERO;
+ default:
+ return null;
+ }
+ }
+
+ static Function _converterForType(int type) {
+ if (((type & _REPEATED_BIT) != 0) || ((type & _PACKED_BIT) != 0)) {
+ return ((type & _BYTES_BIT) != 0) ?
+ _toImmutableListNonGrowable : _toImmutableListIdentity;
+ } else {
+ return ((type & _BYTES_BIT) != 0) ? _toNonGrowableList : _identity;
+ }
+ }
+
+ static Object _identity(Object source) => source;
+
+ static List _toNonGrowableList(List source) {
+ if (source is PbImmutableList) {
+ return source;
+ } else {
+ return new PbImmutableList.from(source);
+ }
+ }
+
+ static List _toImmutableListIdentity(PbList source) {
+ return source.asImmutable();
+ }
+
+ static List _toImmutableListNonGrowable(PbList source) {
+ return source.asImmutable(_toNonGrowableList);
+ }
+
+ Map<int, Dynamic> _fieldValues;
+ bool _isClean;
+ UnknownFieldSet _unknownFields;
+ Map<int, Extension> _extensions;
+
+ Builder()
+ : _unknownFields = UnknownFieldSet.defaultInstance,
+ _fieldValues = new Map<int, Dynamic>() {
+ initialize_();
+ }
+
+ /**
+ * Add an extension field value to a repeated field. The backing
+ * [List] will be created if necessary.
+ */
+ void addExtension(Extension extension, var value) {
+ _checkExtension(extension);
+ if ((extension.type & _REPEATED_BIT) == 0) {
+ throw new PbException(
+ "Cannot add to a non-repeated field (use 'setExtension()')");
+ }
+ // Validate type and range
+ value = _validate(extension.tagNumber, extension.type & ~0x7, value);
+
+ var list = _fieldValues[extension.tagNumber];
+ if (list == null) {
+ list = extension.makeDefault();
+ _setExtension(extension, list);
+ }
+
+ list.add(value);
+ onChanged();
+ }
+
+ Message build() {
+ Message result = buildPartial();
+ if (!isInitialized()) {
+ List<String> invalidFields = <String>[];
+ _findInvalidFields(invalidFields);
+ throw new UninitializedMessageException(invalidFields);
+ }
+ return result;
+ }
+
+ Message buildParsed() {
+ Message result = buildPartial();
+ if (!isInitialized()) {
+ List<String> invalidFields = <String>[];
+ _findInvalidFields(invalidFields);
+ throw new UninitializedMessageException(invalidFields);
+ }
+ return result;
+ }
+
+ abstract Message buildPartial();
+
+ // Shorthand for clearField
+ void c_(int tagNumber) {
+ clearField(tagNumber);
+ }
+
+ void clear() {
+ _unknownFields = UnknownFieldSet.defaultInstance;
+ _fieldValues = new Map<int, Dynamic>();
+ _isClean = true;
+ }
+
+ void clearExtension(Extension extension) {
+ _checkExtension(extension);
+ _fieldValues.remove(extension.tagNumber);
+ Object value = extension.makeDefault();
+ if (value is List) {
+ _setExtension(extension, value);
+ } else {
+ _extensions.remove(extension.tagNumber);
+ }
+ }
+
+ void clearField(int tagNumber) {
+ _fieldValues.remove(tagNumber);
+ // Restore the default value for the field
+ // For repeated fields, the default is an empty list
+ // For required/optional fields, the BuilderInfo contains the initializer
+ int fieldType = _getFieldType(tagNumber);
+ if ((fieldType & _REPEATED_BIT) != 0) {
+ _fieldValues[tagNumber] = new PbList(this);
+ } else {
+ Object defaultValue = info_.defaultValue(tagNumber);
+ if (defaultValue !== null) {
+ _fieldValues[tagNumber] = defaultValue;
+ }
+ }
+ }
+
+ bool extensionsAreInitialized() {
+ if (_extensions == null) {
+ return true;
+ }
+ return _extensions.getKeys().every(bool _(int tagNumber) {
+ return info_._isFieldInitialized(_fieldValues, tagNumber,
+ _extensions[tagNumber].type);
+ });
+ }
+
+ // Allow the contents of each map or set to be changed, but not its reference
+ Map<int, Object> get fieldValues() {
+ // Force initialization of field values to defaults
+ if (info_ !== null) {
+ for (FieldInfo i in info_.fieldInfo.getValues()) {
+ if (i.makeDefault != null) fieldValues [i.tagNumber] = i.makeDefault();
+ }
+ }
+ return _fieldValues;
+ }
+
+ /**
+ * Shorthand for [:getField(tagNumber):].
+ */
+ Dynamic g_(int tagNumber) => getField(tagNumber);
+
+ /**
+ * Returns the value of the given extension. For repeated fields that have
+ * not been set previously, [:null:] is returned.
+ */
+ Dynamic getExtension(Extension extension) {
+ _checkExtension(extension);
+ return getField(extension.tagNumber);
+ }
+
+ /**
+ * Returns the number of elements in the given extension. For repeated fields
+ * that have not been set previously, or for non-repeated fields, [:0:] is
+ * returned.
+ */
+ int getExtensionCount(Extension extension) {
+ _checkExtension(extension);
+ List list = _fieldValues[extension.tagNumber];
+ return (list === null || list is! List) ? 0 : list.length;
+ }
+
+ Object getField(int tagNumber) {
+ var value = _fieldValues[tagNumber];
+ // Initialize the field
+ if (value === null) {
+ MakeDefaultFunc makeDefaultFunc = info_.makeDefault(tagNumber);
+ if (makeDefaultFunc == null) {
+ makeDefaultFunc = _extensions[tagNumber].makeDefault;
+ if (makeDefaultFunc == null) {
+ throw new PbException("Can't make default for field "
+ "${info_.fieldName(tagNumber)} in message ${info_.messageName}");
+ }
+ }
+ value = makeDefaultFunc();
+ _fieldValues[tagNumber] = value;
+ }
+ return value;
+ }
+
+ // Shorthand for hasField
+ bool h_(int tagNumber) => hasField(tagNumber);
+
+ /**
+ * Return [:true:] if a value of the given extension is present.
+ */
+ bool hasExtension(Extension extension) {
+ _checkExtension(extension);
+ return hasField(extension.tagNumber);
+ }
+
+ bool hasField(int tagNumber) {
+ int fieldType = info_.fieldType(tagNumber);
+ if (!_fieldValues.containsKey(tagNumber)) {
+ return false;
+ }
+ var value = _fieldValues[tagNumber];
+ if (value is List && value.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ // Overriden by subclasses
+ abstract BuilderInfo get info_();
+
+ abstract void initialize_();
+
+ bool isInitialized() {
+ if (!info_.hasRequiredFields) {
+ return true;
+ }
+ return info_.isInitialized(_fieldValues) && extensionsAreInitialized();
+ }
+
+ Builder mergeFromBuffer(List<int> input,
+ [ExtensionRegistry extensionRegistry]) {
+ CodedBufferReader codedInput = new CodedBufferReader.fromBuffer(input);
+ extensionRegistry = extensionRegistry == null ?
+ ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
+ mergeFromCodedBufferReader(codedInput, extensionRegistry);
+ codedInput.checkLastTagWas(0);
+ return this;
+ }
+
+ Builder mergeFromCodedBufferReader(CodedBufferReader input,
+ [ExtensionRegistry extensionRegistry]) {
+ UnknownFieldSet_Builder unknownFieldSetBuilder =
+ new UnknownFieldSet_Builder(unknownFields);
+ extensionRegistry = extensionRegistry == null ?
+ ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
+
+ void readPackableIoc(int wireType, int tagNumber, var iocReadFunc) {
+ List list = getField(tagNumber);
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ // Packed
+ int length = input.readInt32();
+ int limit = input._pushLimit(length);
+ while (input.getBytesUntilLimit() > 0) {
+ iocReadFunc((var v) => list.add(v));
+ }
+ input._popLimit(limit);
+ } else {
+ // Not-packed
+ iocReadFunc((var v) => list.add(v));
+ }
+ }
+
+ void readPackable(int wireType, int tagNumber, var readFunc) {
+ readPackableIoc(wireType, tagNumber,
+ (var assigner) => assigner(readFunc()));
+ }
+
+ bool wireTypeMatch(int tagNumber, int fieldType, int wireType) {
+ int fieldDataType = fieldType &
+ ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT);
+ switch (fieldDataType) {
+ case _BOOL_BIT:
+ case _ENUM_BIT:
+ case _INT32_BIT:
+ case _INT64_BIT:
+ case _SINT32_BIT:
+ case _SINT64_BIT:
+ case _UINT32_BIT:
+ case _UINT64_BIT:
+ return wireType == WireFormat.WIRETYPE_VARINT ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case _FLOAT_BIT:
+ case _FIXED32_BIT:
+ case _SFIXED32_BIT:
+ return wireType == WireFormat.WIRETYPE_FIXED32 ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case _DOUBLE_BIT:
+ case _FIXED64_BIT:
+ case _SFIXED64_BIT:
+ return wireType == WireFormat.WIRETYPE_FIXED64 ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case _BYTES_BIT:
+ case _STRING_BIT:
+ case _MESSAGE_BIT:
+ return wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case _GROUP_BIT:
+ return wireType == WireFormat.WIRETYPE_START_GROUP;
+ default:
+ return false;
+ }
+ }
+
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ unknownFields = unknownFieldSetBuilder.build();
+ onChanged();
+ return this;
+ }
+ int wireType = tag & 0x7;
+ int tagNumber = tag >> 3;
+ int fieldType = -1;
+
+ if (info_ != null) {
+ if (info_.containsTagNumber(tagNumber)) {
+ fieldType = info_.fieldType(tagNumber);
+ } else {
+ Extension extension = extensionRegistry
+ .getExtension(info_.messageName, tagNumber);
+ if (extension != null) {
+ _addExtensionToMap(extension);
+ fieldType = extension.type;
+ }
+ }
+ }
+ if (fieldType == -1 || !wireTypeMatch(tagNumber, fieldType, wireType)) {
+ if (!parseUnknownFieldFromBuffer(input, unknownFieldSetBuilder, tag)) {
+ unknownFields = unknownFieldSetBuilder.build();
+ onChanged();
+ return this;
+ } else {
+ continue;
+ }
+ }
+
+ // ignore required/optional packed/unpacked
+ fieldType &= ~(_PACKED_BIT | _REQUIRED_BIT);
+ switch (fieldType) {
+ case _OPTIONAL_BOOL:
+ _fieldValues[tagNumber] = input.readBool();
+ break;
+ case _OPTIONAL_BYTES:
+ _fieldValues[tagNumber] = input.readBytes();
+ break;
+ case _OPTIONAL_STRING:
+ _fieldValues[tagNumber] = input.readString();
+ break;
+ case _OPTIONAL_FLOAT:
+ _fieldValues[tagNumber] = input.readFloat();
+ break;
+ case _OPTIONAL_DOUBLE:
+ _fieldValues[tagNumber] = input.readDouble();
+ break;
+ case _OPTIONAL_ENUM:
+ int rawValue = input.readEnum();
+ var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
+ if (value == null) {
+ unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
+ } else {
+ _fieldValues[tagNumber] = value;
+ }
+ break;
+ case _OPTIONAL_GROUP:
+ Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
+ if (_fieldValues.containsKey(tagNumber)) {
+ subBuilder.mergeFromMessage(getField(tagNumber));
+ }
+ input.readGroup(tagNumber, subBuilder, extensionRegistry);
+ _fieldValues[tagNumber] = subBuilder.buildPartial();
+ break;
+ case _OPTIONAL_INT32:
+ _fieldValues[tagNumber] = input.readInt32();
+ break;
+ case _OPTIONAL_INT64:
+ _fieldValues[tagNumber] = input.readInt64();
+ break;
+ case _OPTIONAL_SINT32:
+ _fieldValues[tagNumber] = input.readSint32();
+ break;
+ case _OPTIONAL_SINT64:
+ _fieldValues[tagNumber] = input.readSint64();
+ break;
+ case _OPTIONAL_UINT32:
+ _fieldValues[tagNumber] = input.readUint32();
+ break;
+ case _OPTIONAL_UINT64:
+ _fieldValues[tagNumber] = input.readUint64();
+ break;
+ case _OPTIONAL_FIXED32:
+ _fieldValues[tagNumber] = input.readFixed32();
+ break;
+ case _OPTIONAL_FIXED64:
+ _fieldValues[tagNumber] = input.readFixed64();
+ break;
+ case _OPTIONAL_SFIXED32:
+ _fieldValues[tagNumber] = input.readSfixed32();
+ break;
+ case _OPTIONAL_SFIXED64:
+ _fieldValues[tagNumber] = input.readSfixed64();
+ break;
+ case _OPTIONAL_MESSAGE:
+ Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
+ if (_fieldValues.containsKey(tagNumber)) {
+ subBuilder.mergeFromMessage(getField(tagNumber));
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ _fieldValues[tagNumber] = subBuilder.buildPartial();
+ break;
+ case _REPEATED_BOOL:
+ readPackable(wireType, tagNumber, input.readBool);
+ break;
+ case _REPEATED_BYTES:
+ List list = getField(tagNumber);
+ list.add(input.readBytes());
+ break;
+ case _REPEATED_STRING:
+ List list = getField(tagNumber);
+ list.add(input.readString());
+ break;
+ case _REPEATED_FLOAT:
+ readPackable(wireType, tagNumber, input.readFloat);
+ break;
+ case _REPEATED_DOUBLE:
+ readPackable(wireType, tagNumber, input.readDouble);
+ break;
+ case _REPEATED_ENUM:
+ readPackableIoc(wireType, tagNumber, (var assigner){
+ int rawValue = input.readEnum();
+ var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
+ if (value == null) {
+ unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
+ } else {
+ assigner(value);
+ }
+ });
+ break;
+ case _REPEATED_GROUP:
+ Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
+ input.readGroup(tagNumber, subBuilder, extensionRegistry);
+ List list = getField(tagNumber);
+ list.add(subBuilder.buildPartial());
+ break;
+ case _REPEATED_INT32:
+ readPackable(wireType, tagNumber, input.readInt32);
+ break;
+ case _REPEATED_INT64:
+ readPackable(wireType, tagNumber, input.readInt64);
+ break;
+ case _REPEATED_SINT32:
+ readPackable(wireType, tagNumber, input.readSint32);
+ break;
+ case _REPEATED_SINT64:
+ readPackable(wireType, tagNumber, input.readSint64);
+ break;
+ case _REPEATED_UINT32:
+ readPackable(wireType, tagNumber, input.readUint32);
+ break;
+ case _REPEATED_UINT64:
+ readPackable(wireType, tagNumber, input.readUint64);
+ break;
+ case _REPEATED_FIXED32:
+ readPackable(wireType, tagNumber, input.readFixed32);
+ break;
+ case _REPEATED_FIXED64:
+ readPackable(wireType, tagNumber, input.readFixed64);
+ break;
+ case _REPEATED_SFIXED32:
+ readPackable(wireType, tagNumber, input.readSfixed32);
+ break;
+ case _REPEATED_SFIXED64:
+ readPackable(wireType, tagNumber, input.readSfixed64);
+ break;
+ case _REPEATED_MESSAGE:
+ Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
+ input.readMessage(subBuilder, extensionRegistry);
+ List list = getField(tagNumber);
+ list.add(subBuilder.buildPartial());
+ break;
+ default:
+ throw "Unknown field type $fieldType";
+ }
+ }
+ }
+
+ /**
+ * Merge field values from a JSON object, encoded as described by
+ * [GeneratedMessage.writeToJson].
+ */
+ Builder mergeFromJson(String json, [ExtensionRegistry extensionRegistry]) {
+ extensionRegistry = extensionRegistry == null ?
+ ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
+ Map<String, Object> parsed = JSON.parse(json);
+ _mergeFromJson(parsed, extensionRegistry);
+ return this;
+ }
+
+ Builder mergeFromMessage(GeneratedMessage other) {
+ for (int tagNumber in other._fieldValues.getKeys()) {
+ var fieldValue = other._fieldValues[tagNumber];
+
+ int fieldType = other._builderInfo.fieldType(tagNumber);
+ if (fieldType != null) {
+ if ((fieldType & _REPEATED_BIT) != 0) {
+ List otherList = fieldValue;
+ if (!otherList.isEmpty()) {
+ List thisList = getField(tagNumber);
+ thisList.addAll(otherList);
+ onChanged();
+ }
+ } else {
+ setField(tagNumber, fieldValue);
+ }
+ } else {
+ Extension extension = other._extensions[tagNumber];
+ _addExtensionToMap(extension);
+ fieldType = extension.type;
+ if ((fieldType & _REPEATED_BIT) != 0) {
+ List otherList = fieldValue;
+ if (!otherList.isEmpty()) {
+ List thisList = extension.makeDefault();
+ thisList.addAll(otherList);
+ _fieldValues[tagNumber] = thisList;
+ onChanged();
+ }
+ } else {
+ setField(tagNumber, fieldValue, fieldType);
+ }
+ }
+ }
+
+ mergeUnknownFields(other.unknownFields);
+ return this;
+ }
+
+ Future<Builder> mergeFromCodedStreamReader(CodedStreamReader input,
+ [ExtensionRegistry extensionRegistry]) {
+ UnknownFieldSet_Builder unknownFieldSetBuilder =
+ new UnknownFieldSet_Builder(unknownFields);
+ extensionRegistry = extensionRegistry == null ?
+ ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
+ Completer<Builder> c = new Completer<Builder>();
+
+ Function merge;
+
+ Function appendAndMerge(int tagNumber) {
+ return Future _(Dynamic value) {
+ List list = getField(tagNumber);
+ list.add(value);
+ return merge();
+ };
+ }
+
+ Function assignAndMerge(int tagNumber) {
+ return Future _(Dynamic value) {
+ _fieldValues[tagNumber] = value;
+ return merge();
+ };
+ }
+
+ // readPackableIoc inverts control in that it takes in a read function
+ // that itself takes a function parameter. This function actually sets the
+ // value in the current message. This is important because the setter method
+ // may need to be substituted in the case that an enum is unresolved.
+ Future readPackableIoc(int wireType, int tagNumber, var iocReadFunc) {
+ List list = getField(tagNumber);
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ // Packed
+ return input.readInt32().chain((int length) {
+ int limit = input._pushLimit(length);
+ Future readUntilLimit() {
+ if (input.getBytesUntilLimit() > 0) {
+ return iocReadFunc((var v) => list.add(v))
+ .chain(() => readUntilLimit());
+ } else {
+ input._popLimit(limit);
+ return merge();
+ }
+ }
+ });
+ } else {
+ // Not-packed
+ return iocReadFunc((var v) => list.add(v)).chain((_) => merge());
+ }
+ }
+
+ Future readPackable(int wireType, int tagNumber, var readFunc) =>
+ readPackableIoc(wireType, tagNumber, _(var assigner) =>
+ readFunc().transform((v) => assigner(v))
+ );
+
+ bool wireTypeMatch(int tagNumber, int fieldType, int wireType) {
+ int fieldDataType = fieldType &
+ ~(Builder._REQUIRED_BIT | Builder._REPEATED_BIT |
+ Builder._PACKED_BIT);
+ switch (fieldDataType) {
+ case Builder._BOOL_BIT:
+ case Builder._ENUM_BIT:
+ case Builder._INT32_BIT:
+ case Builder._INT64_BIT:
+ case Builder._SINT32_BIT:
+ case Builder._SINT64_BIT:
+ case Builder._UINT32_BIT:
+ case Builder._UINT64_BIT:
+ return wireType == WireFormat.WIRETYPE_VARINT ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case Builder._FLOAT_BIT:
+ case Builder._FIXED32_BIT:
+ case Builder._SFIXED32_BIT:
+ return wireType == WireFormat.WIRETYPE_FIXED32 ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case Builder._DOUBLE_BIT:
+ case Builder._FIXED64_BIT:
+ case Builder._SFIXED64_BIT:
+ return wireType == WireFormat.WIRETYPE_FIXED64 ||
+ wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case Builder._BYTES_BIT:
+ case Builder._STRING_BIT:
+ case Builder._MESSAGE_BIT:
+ return wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ case Builder._GROUP_BIT:
+ return wireType == WireFormat.WIRETYPE_START_GROUP;
+ default:
+ return false;
+ }
+ }
+
+ Future readField(int tagNumber, int wireType, int fieldType) {
+ // ignore required/optional packed/unpacked
+ fieldType &= ~(Builder._PACKED_BIT | Builder._REQUIRED_BIT);
+ switch (fieldType) {
+ case Builder._OPTIONAL_BOOL:
+ return input.readBool().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_BYTES:
+ return input.readBytes().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_STRING:
+ return input.readString().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_FLOAT:
+ return input.readFloat().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_DOUBLE:
+ return input.readDouble().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_ENUM:
+ return input.readEnum().chain((int rawValue) {
+ var value = _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
+ if (value == null) {
+ unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
+ } else {
+ _fieldValues[tagNumber] = value;
+ }
+ return merge();
+ });
+ case Builder._OPTIONAL_GROUP:
+ Builder subBuilder = info_.subBuilder(tagNumber)();
+ if (_fieldValues.containsKey(tagNumber)) {
+ subBuilder.mergeFromMessage(getField(tagNumber));
+ }
+ return input.readGroup(tagNumber, subBuilder, extensionRegistry)
+ .chain((_) {
+ _fieldValues[tagNumber] = subBuilder.buildPartial();
+ return merge();
+ });
+ case Builder._OPTIONAL_INT32:
+ return input.readInt32().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_INT64:
+ return input.readInt64().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_SINT32:
+ return input.readSint32().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_SINT64:
+ return input.readSint64().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_UINT32:
+ return input.readUint32().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_UINT64:
+ return input.readUint64().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_FIXED32:
+ return input.readFixed32().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_FIXED64:
+ return input.readFixed64().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_SFIXED32:
+ return input.readSfixed32().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_SFIXED64:
+ return input.readSfixed64().chain(assignAndMerge(tagNumber));
+ case Builder._OPTIONAL_MESSAGE:
+ Builder subBuilder = info_.subBuilder(tagNumber)();
+ if (_fieldValues.containsKey(tagNumber)) {
+ subBuilder.mergeFromMessage(getField(tagNumber));
+ }
+ return input.readMessage(subBuilder, extensionRegistry).chain((_) {
+ _fieldValues[tagNumber] = subBuilder.buildPartial();
+ return merge();
+ });
+ case Builder._REPEATED_BOOL:
+ return readPackable(wireType, tagNumber, input.readBool);
+ case Builder._REPEATED_BYTES:
+ return input.readBytes().chain(appendAndMerge(tagNumber));
+ case Builder._REPEATED_STRING:
+ return input.readString().chain(appendAndMerge(tagNumber));
+ case Builder._REPEATED_FLOAT:
+ return readPackable(wireType, tagNumber, input.readFloat);
+ case Builder._REPEATED_DOUBLE:
+ return readPackable(wireType, tagNumber, input.readDouble);
+ case Builder._REPEATED_ENUM:
+ return readPackableIoc(wireType, tagNumber, (var assigner) =>
+ input.readEnum().transform((int rawValue) {
+ var value =
+ _getValueOfFunc(tagNumber, extensionRegistry)(rawValue);
+ if (value == null) {
+ unknownFieldSetBuilder.mergeVarintField(tagNumber, rawValue);
+ } else {
+ assigner(value);
+ }
+ return null;
+ })
+ );
+ case Builder._REPEATED_GROUP:
+ Builder subBuilder = info_.subBuilder(tagNumber)();
+ return input.readGroup(tagNumber, subBuilder, extensionRegistry)
+ .chain((_) {
+ List list = getField(tagNumber);
+ list.add(subBuilder.buildPartial());
+ return merge();
+ });
+ case Builder._REPEATED_INT32:
+ return readPackable(wireType, tagNumber, input.readInt32);
+ case Builder._REPEATED_INT64:
+ return readPackable(wireType, tagNumber, input.readInt64);
+ case Builder._REPEATED_SINT32:
+ return readPackable(wireType, tagNumber, input.readSint32);
+ case Builder._REPEATED_SINT64:
+ return readPackable(wireType, tagNumber, input.readSint64);
+ case Builder._REPEATED_UINT32:
+ return readPackable(wireType, tagNumber, input.readUint32);
+ case Builder._REPEATED_UINT64:
+ return readPackable(wireType, tagNumber, input.readUint64);
+ case Builder._REPEATED_FIXED32:
+ return readPackable(wireType, tagNumber, input.readFixed32);
+ case Builder._REPEATED_FIXED64:
+ return readPackable(wireType, tagNumber, input.readFixed64);
+ case Builder._REPEATED_SFIXED32:
+ return readPackable(wireType, tagNumber, input.readSfixed32);
+ case Builder._REPEATED_SFIXED64:
+ return readPackable(wireType, tagNumber, input.readSfixed64);
+ case Builder._REPEATED_MESSAGE:
+ Builder subBuilder = info_.subBuilder(tagNumber)();
+ return input.readMessage(subBuilder, extensionRegistry).chain((_) {
+ List list = getField(tagNumber);
+ list.add(subBuilder.buildPartial());
+ return merge();
+ });
+ default:
+ throw "Unknown field type $fieldType";
+ }
+ };
+
+ Future mergeImpl() {
+ return input.readTag().chain((int tag) {
+ if (tag == 0) {
+ unknownFields = unknownFieldSetBuilder.build();
+ onChanged();
+ return new Future.immediate(null);
+ }
+ int wireType = tag & 0x7;
+ int tagNumber = tag >> 3;
+ int fieldType = -1;
+
+ if (info_.containsTagNumber(tagNumber)) {
+ fieldType = info_.fieldType(tagNumber);
+ } else {
+ Extension extension =
+ extensionRegistry.getExtension(info_.messageName, tagNumber);
+ if (extension != null) {
+ _addExtensionToMap(extension);
+ fieldType = extension.type;
+ }
+ }
+ if (fieldType == -1 || !wireTypeMatch(tagNumber, fieldType, wireType)) {
+ return parseUnknownFieldFromStream(input, unknownFieldSetBuilder,
+ extensionRegistry, tag).chain(_(bool unknownTag) {
+ if (!unknownTag) {
+ unknownFields = unknownFieldSetBuilder.build();
+ onChanged();
+ return new Future.immediate(null);
+ } else {
+ return merge();
+ }
+ });
+ }
+ return readField(tagNumber, wireType, fieldType);
+ });
+ };
+ merge = mergeImpl;
+ return merge().transform((_) => this);
+ }
+
+ Future<Builder> mergeFromStream(InputStream input,
+ [ExtensionRegistry extensionRegistry]) {
+ extensionRegistry = extensionRegistry == null ?
+ ExtensionRegistry.EMPTY_REGISTRY : extensionRegistry;
+ CodedStreamReader codedInput = new CodedStreamReader(input);
+ return mergeFromCodedStreamReader(codedInput, extensionRegistry)
+ .transform((_) {
+ codedInput.checkLastTagWas(0);
+ return this;
+ });
+ }
+
+ Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
+ _unknownFields =
+ (new UnknownFieldSet_Builder(_unknownFields))
+ .mergeFromUnknownFieldSet(unknownFields).build();
+ onChanged();
+ return this;
+ }
+
+ void onBuilt() {
+// if (builderParent !== null) {
+// markClean();
+// }
+ }
+
+ void onChanged() {
+// if (_isClean && builderParent !== null) {
+// builderParent.markDirty();
+//
+// // Don't keep dispatching invalidations until build is called again.
+// _isClean = false;
+// }
+ }
+
+ bool parseUnknownFieldFromBuffer(CodedBufferReader input,
+ UnknownFieldSet_Builder unknownFieldSetBuilder, int tag) {
+ // If returns false, the tag is an "end group" which is expected
+ // If returns true, the field is considered unknown.
+ bool val = unknownFieldSetBuilder.mergeFieldFromBuffer(tag, input);
+ return val;
+ }
+
+ Future<bool> parseUnknownFieldFromStream(CodedStreamReader input,
+ UnknownFieldSet_Builder unknownFieldSetBuilder,
+ ExtensionRegistry extensionRegistry, int tag) {
+ // If returns false, the tag is an "end group" which is expected
+ // If returns true, the field is considered unknown.
+ return unknownFieldSetBuilder.mergeFieldFromStream(tag, input);
+ }
+
+ Message partial(GeneratedMessage result) {
+ // Set empty repeating fields
+ info_.fieldInfo.forEach(
+ void _(int tagNumber, FieldInfo fieldInfo){
+ int type = fieldInfo.type;
+ if ((type & _REPEATED_BIT) != 0 && !hasField(tagNumber)) {
+ result._fieldValues[tagNumber] = PbImmutableList.EMPTY;
+ }
+ }
+ );
+
+ // Copy extensions
+ if (_extensions != null) {
+ for (int tagNumber in _extensions.getKeys()) {
+ if (result._extensions == null) {
+ result._extensions = new Map<int, Extension>();
+ }
+ result._extensions[tagNumber] = _extensions[tagNumber];
+ }
+ }
+
+ // Then copy fields that have been set
+ for (int tagNumber in _fieldValues.getKeys()) {
+ if (hasField(tagNumber)) {
+ int type = _getFieldType(tagNumber);
+ result._fieldValues[tagNumber] =
+ _converterForType(type)(_fieldValues[tagNumber]);
+ }
+ }
+
+ onBuilt();
+ return result;
+ }
+
+ // Shorthand for setField
+ void s_(int tagNumber, Object value) {
+ setField(tagNumber, value);
+ }
+
+ /**
+ * Set the value of a non-repeated extension field.
+ */
+ void setExtension(Extension extension, var value) {
+ _checkExtension(extension);
+ _addExtensionToMap(extension);
+ setField(extension.tagNumber, value, extension.type);
+ }
+
+ /**
+ * Sets the value of a given field by its [tagNumber]. Can throw an
+ * [:IllegalArgumentException:] if the value does not match the type
+ * associated with [tagNumber].
+ */
+ void setField(int tagNumber, var value, [int fieldType = null]) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ if (fieldType == null) {
+ if (!info_.containsTagNumber(tagNumber)) {
+ throw new IllegalArgumentException("Unknown tag: $tagNumber");
+ }
+ fieldType = info_.fieldType(tagNumber);
+ }
+ if ((fieldType & _REPEATED_BIT) != 0) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "repeating field (use get + .add())"));
+ }
+
+ // Validate type and range
+ value = _validate(tagNumber, fieldType & ~0x7, value);
+ _fieldValues[tagNumber] = value;
+ onChanged();
+ }
+
+ UnknownFieldSet get unknownFields() => _unknownFields;
+
+ void set unknownFields(UnknownFieldSet unknownFields) {
+ _unknownFields = unknownFields;
+ onChanged();
+ }
+
+ void _addExtensionToMap(Extension extension) {
+ if (_extensions == null) {
+ _extensions = new Map<int, Extension>();
+ }
+ _extensions[extension.tagNumber] = extension;
+ }
+
+ void _checkExtension(Extension extension) {
+ if (extension.extendee != info_.messageName) {
+ throw new IllegalArgumentException(
+ "Extension $extension not legal for message ${info_.messageName}");
+ }
+ }
+
+ // dart2js's implementation of 'x is int' is not reliable
+ bool _isInt(var value) {
+ return (value is num) && (value == value.floor());
+ }
+
+ // Extract a value from its JSON representation
+ Dynamic _convertJsonValue(var value, int tagNumber, int fieldType,
+ ExtensionRegistry extensionRegistry) {
+ // Mask off 'required', 'repeated' and 'packed' bits to obtain base type
+ fieldType &= ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT);
+
+ String expectedType; // for exception message
+ switch (fieldType) {
+ case _BOOL_BIT:
+ if (value is bool) {
+ return value;
+ } else if (value is String) {
+ if (value == "true") {
+ return true;
+ } else if (value == "false") {
+ return false;
+ }
+ }
+ expectedType = 'bool, "true", or "false"';
+ break;
+ case _BYTES_BIT:
+ if (value is String) {
+ return Base64Codec.defaultInstance.decodeAsList(value);
+ }
+ expectedType = 'Base64 String';
+ break;
+ case _STRING_BIT:
+ if (value is String) {
+ return value;
+ }
+ expectedType = "String";
+ break;
+ case _FLOAT_BIT:
+ case _DOUBLE_BIT:
+ // Allow quoted values, although we don't emit them
+ if (value is double) {
+ return value;
+ } else if (value is num) {
+ return value.toDouble();
+ } else if (value is String) {
+ return Math.parseDouble(value);
+ }
+ expectedType = "num or stringified num";
+ break;
+ case _ENUM_BIT:
+ // Allow quoted values, although we don't emit them
+ if (value is String) {
+ value = Math.parseInt(value);
+ }
+ if (_isInt(value)) {
+ return _getValueOfFunc(tagNumber, extensionRegistry)(value.toInt());
+ }
+ expectedType = "int or stringified int";
+ break;
+ case _INT32_BIT:
+ case _SINT32_BIT:
+ case _UINT32_BIT:
+ case _FIXED32_BIT:
+ case _SFIXED32_BIT:
+ // Allow quoted values, although we don't emit them
+ if (_isInt(value)) {
+ return value.toInt();
+ } else if (value is String) {
+ return Math.parseInt(value);
+ }
+ expectedType = "int or stringified int";
+ break;
+ case _INT64_BIT:
+ case _SINT64_BIT:
+ case _UINT64_BIT:
+ case _FIXED64_BIT:
+ case _SFIXED64_BIT:
+ // Allow unquoted values, although we don't emit them
+ // TODO - decode large numbers as Packed64 on JavaScript platforms
+ if (value is String) {
+ return Math.parseInt(value);
+ } else if (_isInt(value)) {
+ return value.toInt();
+ }
+ expectedType = "int or stringified int";
+ break;
+ case _GROUP_BIT:
+ case _MESSAGE_BIT:
+ if (value is Map<String, Object>) {
+ Builder subBuilder = _getSubBuilder(tagNumber, extensionRegistry);
+ subBuilder._mergeFromJson(value, extensionRegistry);
+ return subBuilder.build();
+ }
+ expectedType = "nested message or group";
+ break;
+ default:
+ throw new PbException("Unknown type $fieldType");
+ }
+ throw new PbException("Expected type $expectedType, got $value");
+ }
+
+ void _findInvalidFields(List<String> invalidFields) {
+ info_._findInvalidFields(_fieldValues, invalidFields);
+ invalidFields.sort((a, b) => a.compareTo(b));
+ }
+
+ /**
+ * Returns the type associated with a given tag number, either from the
+ * [BuilderInfo] associated with this [Builder], or from a known extension.
+ * If the type is unknown, [null] is returned.
+ */
+ int _getFieldType(int tagNumber) {
+ int type = info_.fieldType(tagNumber);
+ if (type == null && _extensions != null &&
+ _extensions.containsKey(tagNumber)) {
+ type = _extensions[tagNumber].type;
+ }
+ return type;
+ }
+
+ Builder _getSubBuilder(int tagNumber, ExtensionRegistry extensionRegistry) {
+ CreateBuilderFunc subBuilderFunc = info_.subBuilder(tagNumber);
+ if (subBuilderFunc == null && extensionRegistry != null) {
+ subBuilderFunc = extensionRegistry.getExtension(info_.messageName,
+ tagNumber).subBuilder;
+ }
+ if (subBuilderFunc == null) {
+ throw new PbException("No subbuilder for tag $tagNumber");
+ }
+ return subBuilderFunc();
+ }
+
+ ValueOfFunc _getValueOfFunc(int tagNumber,
+ ExtensionRegistry extensionRegistry) {
+ ValueOfFunc valueOfFunc = info_.valueOfFunc(tagNumber);
+ if (valueOfFunc == null && extensionRegistry != null) {
+ valueOfFunc = extensionRegistry.getExtension(info_.messageName,
+ tagNumber).valueOf;
+ }
+ if (valueOfFunc == null) {
+ throw new PbException("No valueOf for tag $tagNumber");
+ }
+ return valueOfFunc;
+ }
+
+ // Merge fields from a previously decoded JSON object
+ Builder _mergeFromJson(Map<String, Object> json,
+ ExtensionRegistry extensionRegistry) {
+ List<int> tags = new List<int>.from(
+ json.getKeys().map((x) => Math.parseInt(x)));
+ tags.sort((a, b) => a.compareTo(b));
+
+ for (int tagNumber in tags) {
+ var fieldValue = json[tagNumber.toString()];
+ int fieldType = -1;
+
+ Extension extension = null;
+ if (info_.containsTagNumber(tagNumber)) {
+ fieldType = info_.fieldType(tagNumber);
+ } else if (extensionRegistry != null) {
+ extension = extensionRegistry.getExtension(info_.messageName,
+ tagNumber);
+ if (extension == null) {
+ // Unknown extensions can be skipped.
+ continue;
+ }
+ _addExtensionToMap(extension);
+ fieldType = extension.type;
+ }
+ if (fieldType == -1) {
+ throw new PbException("Unknown field type for tag number $tagNumber");
+ }
+ if ((fieldType & _REPEATED_BIT) != 0) {
+ List thisList = getField(tagNumber);
+ if (thisList == null) {
+ thisList = extension.makeDefault();
+ }
+ for (var value in fieldValue) {
+ value = _convertJsonValue(value, tagNumber, fieldType,
+ extensionRegistry);
+ thisList.add(value);
+ }
+ _fieldValues[tagNumber] = thisList;
+ onChanged();
+ } else {
+ var value = _convertJsonValue(fieldValue, tagNumber, fieldType,
+ extensionRegistry);
+ setField(tagNumber, value, fieldType);
+ }
+ }
+ }
+
+ // does not perform validation
+ void _setExtension(Extension extension, var value) {
+ _addExtensionToMap(extension);
+ _fieldValues[extension.tagNumber] = value;
+ }
+
+ String _generateMessage(int tagNumber, var value, String detail) {
+ String fieldName;
+ if (_extensions != null && _extensions[tagNumber] != null) {
+ fieldName = _extensions[tagNumber].name;
+ } else {
+ fieldName = info_.fieldName(tagNumber);
+ }
+ String messageType = info_.messageName;
+ return "Illegal to set field $fieldName ($tagNumber) of $messageType"
+ " to value ($value): $detail";
+ }
+
+ // For int values, force coercion to int since there isn't a reliable
+ // check for int-ness that works in both the VM and dart2js
+ Dynamic _validate(int tagNumber, int fieldType, var value) {
+ switch (fieldType) {
+ case _BOOL_BIT:
+ if (value is !bool) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type bool"));
+ }
+ break;
+ case _BYTES_BIT:
+ if (value is !List<int>) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not List<int>"));
+ }
+ break;
+ case _STRING_BIT:
+ if (value is !String) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type String"));
+ }
+ break;
+ case _FLOAT_BIT:
+ if (value is !double) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type double"));
+ }
+ if (value < -_Constants.MAX_FLOAT || value > _Constants.MAX_FLOAT) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for float"));
+ }
+ break;
+ case _DOUBLE_BIT:
+ if (value is !double) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type double"));
+ }
+ break;
+ case _ENUM_BIT:
+ if (value is !ProtobufEnum) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type ProtobufEnum"));
+ }
+ break;
+ case _INT32_BIT:
+ if (!_isInt(value)) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type int"));
+ }
+ if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for int32"));
+ }
+ value = value.toInt();
+ break;
+ case _INT64_BIT:
+ if (!_isInt(value) && value is !Packed64) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not int or Packed64"));
+ }
+ if (_isInt(value) &&
+ (value < _Constants.MIN_SINT64 || value > _Constants.MAX_SINT64)) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for int64"));
+ }
+ if (value is !Packed64) {
+ value = value.toInt();
+ }
+ break;
+ case _SINT32_BIT:
+ if (!_isInt(value)) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type int"));
+ }
+ if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for sint32"));
+ }
+ value = value.toInt();
+ break;
+ case _SINT64_BIT:
+ if (!_isInt(value) && value is !Packed64) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not int or Packed64"));
+ }
+ if (_isInt(value) &&
+ (value < _Constants.MIN_SINT64 || value > _Constants.MAX_SINT64)) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for sint64"));
+ }
+ if (value is !Packed64) {
+ value = value.toInt();
+ }
+ break;
+ case _UINT32_BIT:
+ if (!_isInt(value)) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type int"));
+ }
+ if (value < 0 || value > _Constants.MAX_UINT32) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for uint32"));
+ }
+ value = value.toInt();
+ break;
+ case _UINT64_BIT:
+ if (!_isInt(value) && value is !Packed64) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not int or Packed64"));
+ }
+ if ((_isInt(value)) && (value < 0 || value > _Constants.MAX_UINT64)) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for uint64"));
+ }
+ if (value is !Packed64) {
+ value = value.toInt();
+ }
+ break;
+ case _FIXED32_BIT:
+ if (!_isInt(value)) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type int"));
+ }
+ if (value < 0 || value > _Constants.MAX_UINT32) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for fixed32"));
+ }
+ break;
+ case _FIXED64_BIT:
+ if (!_isInt(value) && value is !Packed64) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not int or Packed64"));
+ }
+ if ((_isInt(value)) && (value < 0 || value > _Constants.MAX_UINT64)) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for fixed64"));
+ }
+ if (value is !Packed64) {
+ value = value.toInt();
+ }
+ break;
+ case _SFIXED32_BIT:
+ if (!_isInt(value)) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not type int"));
+ }
+ if (value < _Constants.MIN_SINT32 || value > _Constants.MAX_SINT32) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for sfixed32"));
+ }
+ break;
+ case _SFIXED64_BIT:
+ if (!_isInt(value) && value is !Packed64) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not int or Packed64"));
+ }
+ if ((_isInt(value)) && (value < _Constants.MIN_SINT64 ||
+ value > _Constants.MAX_SINT64)) {
+ throw new IllegalArgumentException(_generateMessage(tagNumber, value,
+ "out of range for sfixed64"));
+ }
+ if (value is !Packed64) {
+ value = value.toInt();
+ }
+ break;
+ case _GROUP_BIT:
+ case _MESSAGE_BIT:
+ if (value is !GeneratedMessage) {
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "not a GeneratedMessage"));
+ }
+ break;
+ default:
+ throw new IllegalArgumentException(
+ _generateMessage(tagNumber, value, "field has unknown type "
+ "$fieldType"));
+ }
+ return value;
+ }
+}
« 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