/// <summary> /// Like <see cref="MergeFrom(ICodedInputStream, ExtensionRegistry, IBuilder)" /> /// but parses a single field. /// </summary> /// <param name="input">The input to read the field from</param> /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param> /// <param name="builder">Builder to merge field into, if it's a known field</param> /// <param name="tag">The tag, which should already have been read from the input</param> /// <returns>true unless the tag is an end-group tag</returns> internal bool MergeFieldFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder, uint tag, string fieldName) { if (tag == 0 && fieldName != null) { FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(fieldName); if (fieldByName != null) { tag = WireFormat.MakeTag(fieldByName); } else { ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, fieldName); if (extension != null) { tag = WireFormat.MakeTag(extension.Descriptor); } } } MessageDescriptor type = builder.DescriptorForType; if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) { MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder); return(true); } WireFormat.WireType wireType = WireFormat.GetTagWireType(tag); int fieldNumber = WireFormat.GetTagFieldNumber(tag); FieldDescriptor field; IMessageLite defaultFieldInstance = null; if (type.IsExtensionNumber(fieldNumber)) { ExtensionInfo extension = extensionRegistry[type, fieldNumber]; if (extension == null) { field = null; } else { field = extension.Descriptor; defaultFieldInstance = extension.DefaultInstance; } } else { field = type.FindFieldByNumber(fieldNumber); } // Unknown field or wrong wire type. Skip. if (field == null) { return(MergeFieldFrom(tag, input)); } if (wireType != WireFormat.GetWireType(field)) { WireFormat.WireType expectedType = WireFormat.GetWireType(field.FieldType); if (wireType == expectedType) { //Allowed as of 2.3, this is unpacked data for a packed array } else if (field.IsRepeated && wireType == WireFormat.WireType.LengthDelimited && (expectedType == WireFormat.WireType.Varint || expectedType == WireFormat.WireType.Fixed32 || expectedType == WireFormat.WireType.Fixed64)) { //Allowed as of 2.3, this is packed data for an unpacked array } else { return(MergeFieldFrom(tag, input)); } } switch (field.FieldType) { case FieldType.Group: case FieldType.Message: { IBuilderLite subBuilder = (defaultFieldInstance != null) ? defaultFieldInstance.WeakCreateBuilderForType() : builder.CreateBuilderForField(field); if (!field.IsRepeated) { subBuilder.WeakMergeFrom((IMessageLite)builder[field]); if (field.FieldType == FieldType.Group) { input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry); } else { input.ReadMessage(subBuilder, extensionRegistry); } builder[field] = subBuilder.WeakBuild(); } else { List <IMessageLite> list = new List <IMessageLite>(); if (field.FieldType == FieldType.Group) { input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry); } else { input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry); } foreach (IMessageLite m in list) { builder.WeakAddRepeatedField(field, m); } return(true); } break; } case FieldType.Enum: { if (!field.IsRepeated) { object unknown; IEnumLite value = null; if (input.ReadEnum(ref value, out unknown, field.EnumType)) { builder[field] = value; } else if (unknown is int) { MergeVarintField(fieldNumber, (ulong)(int)unknown); } } else { ICollection <object> unknown; List <IEnumLite> list = new List <IEnumLite>(); input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType); foreach (IEnumLite en in list) { builder.WeakAddRepeatedField(field, en); } if (unknown != null) { foreach (object oval in unknown) { if (oval is int) { MergeVarintField(fieldNumber, (ulong)(int)oval); } } } } break; } default: { if (!field.IsRepeated) { object value = null; if (input.ReadPrimitiveField(field.FieldType, ref value)) { builder[field] = value; } } else { List <object> list = new List <object>(); input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list); foreach (object oval in list) { builder.WeakAddRepeatedField(field, oval); } } break; } } return(true); }
/// <summary> /// Like <see cref="MergeFrom(CodedInputStream, ExtensionRegistry, IBuilder)" /> /// but parses a single field. /// </summary> /// <param name="input">The input to read the field from</param> /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param> /// <param name="builder">Builder to merge field into, if it's a known field</param> /// <param name="tag">The tag, which should already have been read from the input</param> /// <returns>true unless the tag is an end-group tag</returns> internal bool MergeFieldFrom(CodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder, uint tag) { MessageDescriptor type = builder.DescriptorForType; if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) { MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder); return(true); } WireFormat.WireType wireType = WireFormat.GetTagWireType(tag); int fieldNumber = WireFormat.GetTagFieldNumber(tag); FieldDescriptor field; IMessage defaultFieldInstance = null; if (type.IsExtensionNumber(fieldNumber)) { ExtensionInfo extension = extensionRegistry[type, fieldNumber]; if (extension == null) { field = null; } else { field = extension.Descriptor; defaultFieldInstance = extension.DefaultInstance; } } else { field = type.FindFieldByNumber(fieldNumber); } // Unknown field or wrong wire type. Skip. if (field == null || wireType != WireFormat.GetWireType(field)) { return(MergeFieldFrom(tag, input)); } if (field.IsPacked) { int length = (int)input.ReadRawVarint32(); int limit = input.PushLimit(length); if (field.FieldType == FieldType.Enum) { while (!input.ReachedLimit) { int rawValue = input.ReadEnum(); object value = field.EnumType.FindValueByNumber(rawValue); if (value == null) { // If the number isn't recognized as a valid value for this // enum, drop it (don't even add it to unknownFields). return(true); } builder.WeakAddRepeatedField(field, value); } } else { while (!input.ReachedLimit) { Object value = input.ReadPrimitiveField(field.FieldType); builder.WeakAddRepeatedField(field, value); } } input.PopLimit(limit); } else { object value; switch (field.FieldType) { case FieldType.Group: case FieldType.Message: { IBuilder subBuilder; if (defaultFieldInstance != null) { subBuilder = defaultFieldInstance.WeakCreateBuilderForType(); } else { subBuilder = builder.CreateBuilderForField(field); } if (!field.IsRepeated) { subBuilder.WeakMergeFrom((IMessage)builder[field]); } if (field.FieldType == FieldType.Group) { input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry); } else { input.ReadMessage(subBuilder, extensionRegistry); } value = subBuilder.WeakBuild(); break; } case FieldType.Enum: { int rawValue = input.ReadEnum(); value = field.EnumType.FindValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { MergeVarintField(fieldNumber, (ulong)rawValue); return(true); } break; } default: value = input.ReadPrimitiveField(field.FieldType); break; } if (field.IsRepeated) { builder.WeakAddRepeatedField(field, value); } else { builder[field] = value; } } return(true); }