protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { _logger.LogDebug("[{0} --> {1}] Decoding {2} into Protobuf", context.Channel.LocalAddress, context.Channel.RemoteAddress, input); var readable = input.ReadableBytes; var buf = new byte[readable]; input.ReadBytes(buf); var bs = ByteString.CopyFrom(buf); var result = _extensions == null ? _prototype.WeakCreateBuilderForType().WeakMergeFrom(bs).WeakBuild() : _prototype.WeakCreateBuilderForType().WeakMergeFrom(bs, _extensions).WeakBuild(); output.Add(result); }
public virtual TBuilder MergeFrom(IMessage other) { if (other.DescriptorForType != DescriptorForType) { throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); } // Note: We don't attempt to verify that other's fields have valid // types. Doing so would be a losing battle. We'd have to verify // all sub-messages as well, and we'd have to make copies of all of // them to insure that they don't change after verification (since // the Message interface itself cannot enforce immutability of // implementations). // TODO(jonskeet): Provide a function somewhere called MakeDeepCopy() // which allows people to make secure deep copies of messages. foreach (KeyValuePair <FieldDescriptor, object> entry in other.AllFields) { FieldDescriptor field = entry.Key; if (field.IsRepeated) { // Concatenate repeated fields foreach (object element in (IEnumerable)entry.Value) { AddRepeatedField(field, element); } } else if (field.MappedType == MappedType.Message) { // Merge singular messages IMessageLite existingValue = (IMessageLite)this[field]; if (existingValue == existingValue.WeakDefaultInstanceForType) { this[field] = entry.Value; } else { this[field] = existingValue.WeakCreateBuilderForType() .WeakMergeFrom(existingValue) .WeakMergeFrom((IMessageLite)entry.Value) .WeakBuild(); } } else { // Overwrite simple values this[field] = entry.Value; } } //Fix for unknown fields not merging, see java's AbstractMessage.Builder<T> line 236 MergeUnknownFields(other.UnknownFields); return(ThisBuilder); }
/// <summary> /// 解码 /// </summary> /// <param name="data">protobuf编码字节数组</param> /// <returns>返回解码之后的消息</returns> public IMessageLite Decode(byte[] data) { if (_prototype == null) { throw new Exception("_prototype must using InitProtobufDecoder method to initialize."); } IMessageLite message; if (_extensionRegistry == null) { message = (_prototype.WeakCreateBuilderForType().WeakMergeFrom(ByteString.CopyFrom(data))).WeakBuild(); } else { message = (_prototype.WeakCreateBuilderForType().WeakMergeFrom(ByteString.CopyFrom(data), _extensionRegistry)) .WeakBuild(); } if (message == null) { throw new Exception("Decode message failed"); } return(message); }
public override bool ReadMessageArray <T>(string field, ICollection <T> items, IMessageLite messageType, ExtensionRegistry registry) { object[] array = null; if (GetValue(ref array)) { foreach (IDictionary <string, object> item in array) { IBuilderLite builder = messageType.WeakCreateBuilderForType(); new DictionaryReader(item).Merge(builder); items.Add((T)builder.WeakBuild()); } return(true); } return(false); }
/// <summary> /// Reads an array of T messages as a proto-buffer group /// </summary> public virtual bool ReadGroupArray <T>(string field, ICollection <T> items, IMessageLite messageType, ExtensionRegistry registry) { bool success = false; foreach (string next in ForeachArrayItem(field)) { IBuilderLite builder = messageType.WeakCreateBuilderForType(); if (ReadGroup(builder, registry)) { items.Add((T)builder.WeakBuild()); success |= true; } } return(success); }
public override TBuilder MergeFrom(TMessage other) { if (other.DescriptorForType != InternalFieldAccessors.Descriptor) { throw new ArgumentException("Message type mismatch"); } foreach (KeyValuePair <FieldDescriptor, object> entry in other.AllFields) { FieldDescriptor field = entry.Key; if (field.IsRepeated) { // Concatenate repeated fields foreach (object element in (IEnumerable)entry.Value) { AddRepeatedField(field, element); } } else if (field.MappedType == MappedType.Message && HasField(field)) { // Merge singular embedded messages IMessageLite oldValue = (IMessageLite)this[field]; this[field] = oldValue.WeakCreateBuilderForType() .WeakMergeFrom(oldValue) .WeakMergeFrom((IMessageLite)entry.Value) .WeakBuildPartial(); } else { // Just overwrite this[field] = entry.Value; } } //Fix for unknown fields not merging, see java's AbstractMessage.Builder<T> line 236 MergeUnknownFields(other.UnknownFields); return(ThisBuilder); }
public void TestIMessageLiteWeakCreateBuilderForType() { IMessageLite msg = TestRequiredLite.DefaultInstance; Assert.AreEqual(typeof(TestRequiredLite.Builder), msg.WeakCreateBuilderForType().GetType()); }
/// <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; 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 || 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: { IBuilderLite subBuilder; if (defaultFieldInstance != null) { subBuilder = defaultFieldInstance.WeakCreateBuilderForType(); } else { subBuilder = 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); } 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); }