Index: lib/generated_message.dart |
diff --git a/lib/generated_message.dart b/lib/generated_message.dart |
index adfda25e5e482fb8ee30aae46b9223c8108c9336..55cc9ecef2ff7bd69494b1863efa4f1478a2954c 100644 |
--- a/lib/generated_message.dart |
+++ b/lib/generated_message.dart |
@@ -279,7 +279,41 @@ abstract class GeneratedMessage { |
return true; |
} |
- int get hashCode => _fieldValues.hashCode; |
+ int get hashCode { |
+ int hash; |
+ |
+ void hashEnumList(PbList enums) { |
+ enums.forEach((enum) { |
+ hash = (31 * hash + enum.value) & 0x3fffffff; |
+ }); |
+ } |
+ |
+ void hashFields() { |
+ for (int tagNumber in sorted(_fieldValues.keys)) { |
+ if (!hasField(tagNumber)) continue; |
+ var value = _fieldValues[tagNumber]; |
+ hash = ((37 * hash) + tagNumber) & 0x3fffffff; |
+ int fieldType = _getFieldType(tagNumber); |
+ if (_toBaseFieldType(fieldType) != _ENUM_BIT) { |
+ hash = ((53 * hash) + value.hashCode) & 0x3fffffff; |
+ } else if ((fieldType & _REPEATED_BIT) != 0) { |
+ hashEnumList(value); |
+ } else { |
+ hash = ((53 * hash) + value.value) & 0x3fffffff; |
+ } |
+ } |
+ } |
+ |
+ // Generate hash. |
+ hash = 41; |
+ // Hash with descriptor. |
+ hash = ((19 * hash) + info_.hashCode) & 0x3fffffff; |
+ // Hash with fields. |
+ hashFields(); |
+ // Hash with unknown fields. |
+ hash = ((29 * hash) + unknownFields.hashCode) & 0x3fffffff; |
+ return hash; |
+ } |
String toString() => _toString(''); |
@@ -372,9 +406,7 @@ abstract class GeneratedMessage { |
} |
bool wireTypeMatch(int tagNumber, int fieldType, int wireType) { |
- int fieldDataType = fieldType & |
- ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT); |
- switch (fieldDataType) { |
+ switch (_toBaseFieldType(fieldType)) { |
case _BOOL_BIT: |
case _ENUM_BIT: |
case _INT32_BIT: |
@@ -671,11 +703,8 @@ abstract class GeneratedMessage { |
ExtensionRegistry extensionRegistry) { |
// Extract a value from its JSON representation. |
convertJsonValue(var value, int tagNumber, int fieldType) { |
- // 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) { |
+ switch (_toBaseFieldType(fieldType)) { |
case _BOOL_BIT: |
if (value is bool) { |
return value; |
@@ -997,6 +1026,27 @@ abstract class GeneratedMessage { |
return type; |
} |
+ /** |
+ * Returns the type associated with a given tag number, either from the |
+ * [BuilderInfo] associated with this [GeneratedMessage], |
+ * or from a known extension. If the type is unknown, [null] is returned. |
+ */ |
+ int _getBaseFieldType(int tagNumber) { |
+ int type = info_.fieldType(tagNumber); |
+ if (type == null && _extensions.containsKey(tagNumber)) { |
+ type = _extensions[tagNumber].type; |
+ } |
+ return type; |
+ } |
+ |
+ /* |
+ * Returns the base field type without any of the required, repeated |
+ * and packed bits. |
+ */ |
+ int _toBaseFieldType(int fieldType) { |
+ return fieldType & ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT); |
+ } |
+ |
GeneratedMessage _getEmptyMessage( |
int tagNumber, ExtensionRegistry extensionRegistry) { |
CreateBuilderFunc subBuilderFunc = info_.subBuilder(tagNumber); |