aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers/UnknownFieldSet.cs
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2015-06-09 19:30:44 +0100
committerJon Skeet <skeet@pobox.com>2015-06-09 19:30:44 +0100
commite38294a62d7f37c0661273a9a26fda16d557423f (patch)
tree316989251907553408e7b32a12792f496333e075 /csharp/src/ProtocolBuffers/UnknownFieldSet.cs
parentf52426827e4d5e8da7d205af538799740b5199b9 (diff)
downloadprotobuf-e38294a62d7f37c0661273a9a26fda16d557423f.tar.gz
protobuf-e38294a62d7f37c0661273a9a26fda16d557423f.tar.bz2
protobuf-e38294a62d7f37c0661273a9a26fda16d557423f.zip
First pass at the mutable API. Quite a bit more to do - in particular, it's pretty slow right now.
Diffstat (limited to 'csharp/src/ProtocolBuffers/UnknownFieldSet.cs')
-rw-r--r--csharp/src/ProtocolBuffers/UnknownFieldSet.cs1061
1 files changed, 0 insertions, 1061 deletions
diff --git a/csharp/src/ProtocolBuffers/UnknownFieldSet.cs b/csharp/src/ProtocolBuffers/UnknownFieldSet.cs
deleted file mode 100644
index d5d0675d..00000000
--- a/csharp/src/ProtocolBuffers/UnknownFieldSet.cs
+++ /dev/null
@@ -1,1061 +0,0 @@
-#region Copyright notice and license
-
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Google.ProtocolBuffers.Collections;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers
-{
- /// <summary>
- /// Used to keep track of fields which were seen when parsing a protocol message
- /// but whose field numbers or types are unrecognized. This most frequently
- /// occurs when new fields are added to a message type and then messages containing
- /// those fields are read by old software that was built before the new types were
- /// added.
- ///
- /// Every message contains an UnknownFieldSet.
- ///
- /// Most users will never need to use this class directly.
- /// </summary>
- public sealed partial class UnknownFieldSet : IMessageLite
- {
- private static readonly UnknownFieldSet defaultInstance =
- new UnknownFieldSet(new Dictionary<int, UnknownField>());
-
- private readonly IDictionary<int, UnknownField> fields;
-
- private UnknownFieldSet(IDictionary<int, UnknownField> fields)
- {
- this.fields = fields;
- }
-
- /// <summary>
- /// Creates a new unknown field set builder.
- /// </summary>
- public static Builder CreateBuilder()
- {
- return new Builder();
- }
-
- /// <summary>
- /// Creates a new unknown field set builder
- /// and initialize it from <paramref name="original"/>.
- /// </summary>
- public static Builder CreateBuilder(UnknownFieldSet original)
- {
- return new Builder().MergeFrom(original);
- }
-
- public static UnknownFieldSet DefaultInstance
- {
- get { return defaultInstance; }
- }
-
- /// <summary>
- /// Returns a read-only view of the mapping from field numbers to values.
- /// </summary>
- public IDictionary<int, UnknownField> FieldDictionary
- {
- get { return Dictionaries.AsReadOnly(fields); }
- }
-
- /// <summary>
- /// Checks whether or not the given field number is present in the set.
- /// </summary>
- public bool HasField(int field)
- {
- return fields.ContainsKey(field);
- }
-
- /// <summary>
- /// Fetches a field by number, returning an empty field if not present.
- /// Never returns null.
- /// </summary>
- public UnknownField this[int number]
- {
- get
- {
- UnknownField ret;
- if (!fields.TryGetValue(number, out ret))
- {
- ret = UnknownField.DefaultInstance;
- }
- return ret;
- }
- }
-
- /// <summary>
- /// Serializes the set and writes it to <paramref name="output"/>.
- /// </summary>
- public void WriteTo(ICodedOutputStream output)
- {
- // Avoid creating enumerator for the most common code path.
- if (fields.Count > 0)
- {
- foreach (KeyValuePair<int, UnknownField> entry in fields)
- {
- entry.Value.WriteTo(entry.Key, output);
- }
- }
- }
-
- /// <summary>
- /// Gets the number of bytes required to encode this set.
- /// </summary>
- public int SerializedSize
- {
- get
- {
- // Avoid creating enumerator for the most common code path.
- if (fields.Count == 0)
- {
- return 0;
- }
-
- int result = 0;
- foreach (KeyValuePair<int, UnknownField> entry in fields)
- {
- result += entry.Value.GetSerializedSize(entry.Key);
- }
- return result;
- }
- }
-
- /// <summary>
- /// Converts the set to a string in protocol buffer text format. This
- /// is just a trivial wrapper around TextFormat.PrintToString.
- /// </summary>
- public override String ToString()
- {
- return TextFormat.PrintToString(this);
- }
-
- /// <summary>
- /// Converts the set to a string in protocol buffer text format. This
- /// is just a trivial wrapper around TextFormat.PrintToString.
- /// </summary>
- public void PrintTo(TextWriter writer)
- {
- TextFormat.Print(this, writer);
- }
-
- /// <summary>
- /// Serializes the message to a ByteString and returns it. This is
- /// just a trivial wrapper around WriteTo(ICodedOutputStream).
- /// </summary>
- /// <returns></returns>
- public ByteString ToByteString()
- {
- ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize);
- WriteTo(codedBuilder.CodedOutput);
- return codedBuilder.Build();
- }
-
- /// <summary>
- /// Serializes the message to a byte array and returns it. This is
- /// just a trivial wrapper around WriteTo(ICodedOutputStream).
- /// </summary>
- /// <returns></returns>
- public byte[] ToByteArray()
- {
- byte[] data = new byte[SerializedSize];
- CodedOutputStream output = CodedOutputStream.CreateInstance(data);
- WriteTo(output);
- output.CheckNoSpaceLeft();
- return data;
- }
-
- /// <summary>
- /// Serializes the message and writes it to <paramref name="output"/>. This is
- /// just a trivial wrapper around WriteTo(ICodedOutputStream).
- /// </summary>
- /// <param name="output"></param>
- public void WriteTo(Stream output)
- {
- CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
- WriteTo(codedOutput);
- codedOutput.Flush();
- }
-
- /// <summary>
- /// Serializes the set and writes it to <paramref name="output"/> using
- /// the MessageSet wire format.
- /// </summary>
- public void WriteAsMessageSetTo(ICodedOutputStream output)
- {
- // Avoid creating enumerator for the most common code path.
- if (fields.Count > 0)
- {
- foreach (KeyValuePair<int, UnknownField> entry in fields)
- {
- entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output);
- }
- }
- }
-
- /// <summary>
- /// Gets the number of bytes required to encode this set using the MessageSet
- /// wire format.
- /// </summary>
- public int SerializedSizeAsMessageSet
- {
- get
- {
- // Avoid creating enumerator for the most common code path.
- if (fields.Count == 0)
- {
- return 0;
- }
-
- int result = 0;
- foreach (KeyValuePair<int, UnknownField> entry in fields)
- {
- result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key);
- }
- return result;
- }
- }
-
- public override bool Equals(object other)
- {
- if (ReferenceEquals(this, other))
- {
- return true;
- }
- UnknownFieldSet otherSet = other as UnknownFieldSet;
- return otherSet != null && Dictionaries.Equals(fields, otherSet.fields);
- }
-
- public override int GetHashCode()
- {
- return Dictionaries.GetHashCode(fields);
- }
-
- /// <summary>
- /// Parses an UnknownFieldSet from the given input.
- /// </summary>
- public static UnknownFieldSet ParseFrom(ICodedInputStream input)
- {
- return CreateBuilder().MergeFrom(input).Build();
- }
-
- /// <summary>
- /// Parses an UnknownFieldSet from the given data.
- /// </summary>
- public static UnknownFieldSet ParseFrom(ByteString data)
- {
- return CreateBuilder().MergeFrom(data).Build();
- }
-
- /// <summary>
- /// Parses an UnknownFieldSet from the given data.
- /// </summary>
- public static UnknownFieldSet ParseFrom(byte[] data)
- {
- return CreateBuilder().MergeFrom(data).Build();
- }
-
- /// <summary>
- /// Parses an UnknownFieldSet from the given input.
- /// </summary>
- public static UnknownFieldSet ParseFrom(Stream input)
- {
- return CreateBuilder().MergeFrom(input).Build();
- }
-
- #region IMessageLite Members
-
- public bool IsInitialized
- {
- get { return fields != null; }
- }
-
- public void WriteDelimitedTo(Stream output)
- {
- CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
- codedOutput.WriteRawVarint32((uint) SerializedSize);
- WriteTo(codedOutput);
- codedOutput.Flush();
- }
-
- public IBuilderLite WeakCreateBuilderForType()
- {
- return new Builder();
- }
-
- public IBuilderLite WeakToBuilder()
- {
- return new Builder(fields);
- }
-
- public IMessageLite WeakDefaultInstanceForType
- {
- get { return defaultInstance; }
- }
-
- #endregion
-
- /// <summary>
- /// Builder for UnknownFieldSets.
- /// </summary>
- public sealed partial class Builder : IBuilderLite
- {
- /// <summary>
- /// Mapping from number to field. Note that by using a SortedList we ensure
- /// that the fields will be serialized in ascending order.
- /// </summary>
- private IDictionary<int, UnknownField> fields;
-
- // Optimization: We keep around a builder for the last field that was
- // modified so that we can efficiently add to it multiple times in a
- // row (important when parsing an unknown repeated field).
- private int lastFieldNumber;
- private UnknownField.Builder lastField;
-
- internal Builder()
- {
- fields = new SortedDictionary<int, UnknownField>();
- }
-
- internal Builder(IDictionary<int, UnknownField> dictionary)
- {
- fields = new SortedDictionary<int, UnknownField>(dictionary);
- }
-
- /// <summary>
- /// Returns a field builder for the specified field number, including any values
- /// which already exist.
- /// </summary>
- private UnknownField.Builder GetFieldBuilder(int number)
- {
- if (lastField != null)
- {
- if (number == lastFieldNumber)
- {
- return lastField;
- }
- // Note: AddField() will reset lastField and lastFieldNumber.
- AddField(lastFieldNumber, lastField.Build());
- }
- if (number == 0)
- {
- return null;
- }
-
- lastField = UnknownField.CreateBuilder();
- UnknownField existing;
- if (fields.TryGetValue(number, out existing))
- {
- lastField.MergeFrom(existing);
- }
- lastFieldNumber = number;
- return lastField;
- }
-
- /// <summary>
- /// Build the UnknownFieldSet and return it. Once this method has been called,
- /// this instance will no longer be usable. Calling any method after this
- /// will throw a NullReferenceException.
- /// </summary>
- public UnknownFieldSet Build()
- {
- GetFieldBuilder(0); // Force lastField to be built.
- UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields);
- fields = null;
- return result;
- }
-
- /// <summary>
- /// Adds a field to the set. If a field with the same number already exists, it
- /// is replaced.
- /// </summary>
- public Builder AddField(int number, UnknownField field)
- {
- if (number == 0)
- {
- throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
- }
- if (lastField != null && lastFieldNumber == number)
- {
- // Discard this.
- lastField = null;
- lastFieldNumber = 0;
- }
- fields[number] = field;
- return this;
- }
-
- /// <summary>
- /// Resets the builder to an empty set.
- /// </summary>
- public Builder Clear()
- {
- fields.Clear();
- lastFieldNumber = 0;
- lastField = null;
- return this;
- }
-
- /// <summary>
- /// Parse an entire message from <paramref name="input"/> and merge
- /// its fields into this set.
- /// </summary>
- public Builder MergeFrom(ICodedInputStream input)
- {
- uint tag;
- string name;
- while (input.ReadTag(out tag, out name))
- {
- if (tag == 0)
- {
- if (input.SkipField())
- {
- continue; //can't merge unknown without field tag
- }
- break;
- }
-
- if (!MergeFieldFrom(tag, input))
- {
- break;
- }
- }
- return this;
- }
-
- /// <summary>
- /// Parse a single field from <paramref name="input"/> and merge it
- /// into this set.
- /// </summary>
- /// <param name="tag">The field's tag number, which was already parsed.</param>
- /// <param name="input">The coded input stream containing the field</param>
- /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
- public bool MergeFieldFrom(uint tag, ICodedInputStream input)
- {
- if (tag == 0)
- {
- input.SkipField();
- return true;
- }
-
- int number = WireFormat.GetTagFieldNumber(tag);
- switch (WireFormat.GetTagWireType(tag))
- {
- case WireFormat.WireType.Varint:
- {
- ulong uint64 = 0;
- if (input.ReadUInt64(ref uint64))
- {
- GetFieldBuilder(number).AddVarint(uint64);
- }
- return true;
- }
- case WireFormat.WireType.Fixed32:
- {
- uint uint32 = 0;
- if (input.ReadFixed32(ref uint32))
- {
- GetFieldBuilder(number).AddFixed32(uint32);
- }
- return true;
- }
- case WireFormat.WireType.Fixed64:
- {
- ulong uint64 = 0;
- if (input.ReadFixed64(ref uint64))
- {
- GetFieldBuilder(number).AddFixed64(uint64);
- }
- return true;
- }
- case WireFormat.WireType.LengthDelimited:
- {
- ByteString bytes = null;
- if (input.ReadBytes(ref bytes))
- {
- GetFieldBuilder(number).AddLengthDelimited(bytes);
- }
- return true;
- }
- case WireFormat.WireType.StartGroup:
- {
- Builder subBuilder = CreateBuilder();
-#pragma warning disable 0612
- input.ReadUnknownGroup(number, subBuilder);
-#pragma warning restore 0612
- GetFieldBuilder(number).AddGroup(subBuilder.Build());
- return true;
- }
- case WireFormat.WireType.EndGroup:
- return false;
- default:
- throw InvalidProtocolBufferException.InvalidWireType();
- }
- }
-
- /// <summary>
- /// Parses <paramref name="input"/> as an UnknownFieldSet and merge it
- /// with the set being built. This is just a small wrapper around
- /// MergeFrom(ICodedInputStream).
- /// </summary>
- public Builder MergeFrom(Stream input)
- {
- CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
- MergeFrom(codedInput);
- codedInput.CheckLastTagWas(0);
- return this;
- }
-
- /// <summary>
- /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
- /// with the set being built. This is just a small wrapper around
- /// MergeFrom(ICodedInputStream).
- /// </summary>
- public Builder MergeFrom(ByteString data)
- {
- CodedInputStream input = data.CreateCodedInput();
- MergeFrom(input);
- input.CheckLastTagWas(0);
- return this;
- }
-
- /// <summary>
- /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
- /// with the set being built. This is just a small wrapper around
- /// MergeFrom(ICodedInputStream).
- /// </summary>
- public Builder MergeFrom(byte[] data)
- {
- CodedInputStream input = CodedInputStream.CreateInstance(data);
- MergeFrom(input);
- input.CheckLastTagWas(0);
- return this;
- }
-
- /// <summary>
- /// Convenience method for merging a new field containing a single varint
- /// value. This is used in particular when an unknown enum value is
- /// encountered.
- /// </summary>
- public Builder MergeVarintField(int number, ulong value)
- {
- if (number == 0)
- {
- throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
- }
- GetFieldBuilder(number).AddVarint(value);
- return this;
- }
-
- /// <summary>
- /// Merges the fields from <paramref name="other"/> into this set.
- /// If a field number exists in both sets, the values in <paramref name="other"/>
- /// will be appended to the values in this set.
- /// </summary>
- public Builder MergeFrom(UnknownFieldSet other)
- {
- if (other != DefaultInstance)
- {
- foreach (KeyValuePair<int, UnknownField> entry in other.fields)
- {
- MergeField(entry.Key, entry.Value);
- }
- }
- return this;
- }
-
- /// <summary>
- /// Checks if the given field number is present in the set.
- /// </summary>
- public bool HasField(int number)
- {
- if (number == 0)
- {
- throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
- }
- return number == lastFieldNumber || fields.ContainsKey(number);
- }
-
- /// <summary>
- /// Adds a field to the unknown field set. If a field with the same
- /// number already exists, the two are merged.
- /// </summary>
- public Builder MergeField(int number, UnknownField field)
- {
- if (number == 0)
- {
- throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
- }
- if (HasField(number))
- {
- GetFieldBuilder(number).MergeFrom(field);
- }
- else
- {
- // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
- // in this case, but that would create a copy of the Field object.
- // We'd rather reuse the one passed to us, so call AddField() instead.
- AddField(number, field);
- }
- return this;
- }
-
- internal void MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder)
- {
- uint tag;
- string name;
- while (input.ReadTag(out tag, out name))
- {
- if (tag == 0 && name != null)
- {
- FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(name);
- if (fieldByName != null)
- {
- tag = WireFormat.MakeTag(fieldByName);
- }
- else
- {
- ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, name);
- if (extension != null)
- {
- tag = WireFormat.MakeTag(extension.Descriptor);
- }
- }
- }
- if (tag == 0)
- {
- if (input.SkipField())
- {
- continue; //can't merge unknown without field tag
- }
- break;
- }
-
- if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name))
- {
- // end group tag
- break;
- }
- }
- }
-
- /// <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>
- /// Called by MergeFieldFrom to parse a MessageSet extension.
- /// </summary>
- private void MergeMessageSetExtensionFromCodedStream(ICodedInputStream input,
- ExtensionRegistry extensionRegistry, IBuilder builder)
- {
- MessageDescriptor type = builder.DescriptorForType;
-
- // The wire format for MessageSet is:
- // message MessageSet {
- // repeated group Item = 1 {
- // required int32 typeId = 2;
- // required bytes message = 3;
- // }
- // }
- // "typeId" is the extension's field number. The extension can only be
- // a message type, where "message" contains the encoded bytes of that
- // message.
- //
- // In practice, we will probably never see a MessageSet item in which
- // the message appears before the type ID, or where either field does not
- // appear exactly once. However, in theory such cases are valid, so we
- // should be prepared to accept them.
-
- int typeId = 0;
- ByteString rawBytes = null; // If we encounter "message" before "typeId"
- IBuilderLite subBuilder = null;
- FieldDescriptor field = null;
-
- uint lastTag = WireFormat.MessageSetTag.ItemStart;
- uint tag;
- string name;
- while (input.ReadTag(out tag, out name))
- {
- if (tag == 0 && name != null)
- {
- if (name == "type_id")
- {
- tag = WireFormat.MessageSetTag.TypeID;
- }
- else if (name == "message")
- {
- tag = WireFormat.MessageSetTag.Message;
- }
- }
- if (tag == 0)
- {
- if (input.SkipField())
- {
- continue; //can't merge unknown without field tag
- }
- break;
- }
-
- lastTag = tag;
- if (tag == WireFormat.MessageSetTag.TypeID)
- {
- typeId = 0;
- // Zero is not a valid type ID.
- if (input.ReadInt32(ref typeId) && typeId != 0)
- {
- ExtensionInfo extension = extensionRegistry[type, typeId];
- if (extension != null)
- {
- field = extension.Descriptor;
- subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
- IMessageLite originalMessage = (IMessageLite) builder[field];
- if (originalMessage != null)
- {
- subBuilder.WeakMergeFrom(originalMessage);
- }
- if (rawBytes != null)
- {
- // We already encountered the message. Parse it now.
- // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
- // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
- subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
- rawBytes = null;
- }
- }
- else
- {
- // Unknown extension number. If we already saw data, put it
- // in rawBytes.
- if (rawBytes != null)
- {
- MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
- rawBytes = null;
- }
- }
- }
- }
- else if (tag == WireFormat.MessageSetTag.Message)
- {
- if (subBuilder != null)
- {
- // We already know the type, so we can parse directly from the input
- // with no copying. Hooray!
- input.ReadMessage(subBuilder, extensionRegistry);
- }
- else if (input.ReadBytes(ref rawBytes))
- {
- if (typeId != 0)
- {
- // We don't know how to parse this. Ignore it.
- MergeField(typeId,
- UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
- }
- }
- }
- else
- {
- // Unknown tag. Skip it.
- if (!input.SkipField())
- {
- break; // end of group
- }
- }
- }
-
- if (lastTag != WireFormat.MessageSetTag.ItemEnd)
- {
- throw InvalidProtocolBufferException.InvalidEndTag();
- }
-
- if (subBuilder != null)
- {
- builder[field] = subBuilder.WeakBuild();
- }
- }
-
- #region IBuilderLite Members
-
- bool IBuilderLite.IsInitialized
- {
- get { return fields != null; }
- }
-
- IBuilderLite IBuilderLite.WeakClear()
- {
- return Clear();
- }
-
- IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message)
- {
- return MergeFrom((UnknownFieldSet) message);
- }
-
- IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data)
- {
- return MergeFrom(data);
- }
-
- IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry)
- {
- return MergeFrom(data);
- }
-
- IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input)
- {
- return MergeFrom(input);
- }
-
- IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input, ExtensionRegistry registry)
- {
- return MergeFrom(input);
- }
-
- IMessageLite IBuilderLite.WeakBuild()
- {
- return Build();
- }
-
- IMessageLite IBuilderLite.WeakBuildPartial()
- {
- return Build();
- }
-
- IBuilderLite IBuilderLite.WeakClone()
- {
- return Build().WeakToBuilder();
- }
-
- IMessageLite IBuilderLite.WeakDefaultInstanceForType
- {
- get { return DefaultInstance; }
- }
-
- #endregion
- }
- }
-} \ No newline at end of file