// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. // http://code.google.com/p/protobuf/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Collections.Generic; using System.Collections.ObjectModel; using Google.ProtocolBuffers.Collections; namespace Google.ProtocolBuffers { /// /// Represents a single field in an UnknownFieldSet. /// /// An UnknownField consists of five lists of values. The lists correspond /// to the five "wire types" used in the protocol buffer binary format. /// The wire type of each field can be determined from the encoded form alone, /// without knowing the field's declared type. So, we are able to parse /// unknown values at least this far and separate them. Normally, only one /// of the five lists will contain any values, since it is impossible to /// define a valid message type that declares two different types for the /// same field number. However, the code is designed to allow for the case /// where the same unknown field number is encountered using multiple different /// wire types. /// /// UnknownField is an immutable class. To construct one, you must use an /// UnknownField.Builder. /// public sealed class UnknownField { private static readonly UnknownField defaultInstance = CreateBuilder().Build(); private readonly ReadOnlyCollection varintList; private readonly ReadOnlyCollection fixed32List; private readonly ReadOnlyCollection fixed64List; private readonly ReadOnlyCollection lengthDelimitedList; private readonly ReadOnlyCollection groupList; private UnknownField(ReadOnlyCollection varintList, ReadOnlyCollection fixed32List, ReadOnlyCollection fixed64List, ReadOnlyCollection lengthDelimitedList, ReadOnlyCollection groupList) { this.varintList = varintList; this.fixed32List = fixed32List; this.fixed64List = fixed64List; this.lengthDelimitedList = lengthDelimitedList; this.groupList = groupList; } public static UnknownField DefaultInstance { get { return defaultInstance; } } /// /// The list of varint values for this field. /// public IList VarintList { get { return varintList; } } /// /// The list of fixed32 values for this field. /// public IList Fixed32List { get { return fixed32List; } } /// /// The list of fixed64 values for this field. /// public IList Fixed64List { get { return fixed64List; } } /// /// The list of length-delimited values for this field. /// public IList LengthDelimitedList { get { return lengthDelimitedList; } } /// /// The list of embedded group values for this field. These /// are represented using UnknownFieldSets rather than Messages /// since the group's type is presumably unknown. /// public IList GroupList { get { return groupList; } } /// /// Constructs a new Builder. /// public static Builder CreateBuilder() { return new Builder(); } /// /// Constructs a new Builder and initializes it to a copy of . /// public static Builder CreateBuilder(UnknownField copyFrom) { return new Builder().MergeFrom(copyFrom); } /// /// Serializes the field, including the field number, and writes it to /// . /// public void WriteTo(int fieldNumber, CodedOutputStream output) { foreach (ulong value in varintList) { output.WriteUInt64(fieldNumber, value); } foreach (uint value in fixed32List) { output.WriteFixed32(fieldNumber, value); } foreach (ulong value in fixed64List) { output.WriteFixed64(fieldNumber, value); } foreach (ByteString value in lengthDelimitedList) { output.WriteBytes(fieldNumber, value); } foreach (UnknownFieldSet value in groupList) { output.WriteUnknownGroup(fieldNumber, value); } } /// /// Computes the number of bytes required to encode this field, including field /// number. /// public int GetSerializedSize(int fieldNumber) { int result = 0; foreach (ulong value in varintList) { result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value); } foreach (uint value in fixed32List) { result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value); } foreach (ulong value in fixed64List) { result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value); } foreach (ByteString value in lengthDelimitedList) { result += CodedOutputStream.ComputeBytesSize(fieldNumber, value); } foreach (UnknownFieldSet value in groupList) { result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value); } return result; } /// /// Serializes the length-delimited values of the field, including field /// number, and writes them to using the MessageSet wire format. /// /// /// public void WriteAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output) { foreach (ByteString value in lengthDelimitedList) { output.WriteRawMessageSetExtension(fieldNumber, value); } } /// /// Get the number of bytes required to encode this field, incuding field number, /// using the MessageSet wire format. /// public int GetSerializedSizeAsMessageSetExtension(int fieldNumber) { int result = 0; foreach (ByteString value in lengthDelimitedList) { result += CodedOutputStream.ComputeRawMessageSetExtensionSize(fieldNumber, value); } return result; } /// /// Used to build instances of UnknownField. /// public sealed class Builder { private List varintList; private List fixed32List; private List fixed64List; private List lengthDelimitedList; private List groupList; /// /// Builds the field. After building, the builder is reset to an empty /// state. (This is actually easier than making it unusable.) /// public UnknownField Build() { return new UnknownField(MakeReadOnly(ref varintList), MakeReadOnly(ref fixed32List), MakeReadOnly(ref fixed64List), MakeReadOnly(ref lengthDelimitedList), MakeReadOnly(ref groupList)); } /// /// Merge the values in into this field. For each list /// of values, 's values are append to the ones in this /// field. /// public Builder MergeFrom(UnknownField other) { varintList = AddAll(varintList, other.VarintList); fixed32List = AddAll(fixed32List, other.Fixed32List); fixed64List = AddAll(fixed64List, other.Fixed64List); lengthDelimitedList = AddAll(lengthDelimitedList, other.LengthDelimitedList); groupList = AddAll(groupList, other.GroupList); return this; } /// /// Returns a new list containing all of the given specified values from /// both the and lists. /// If is null and is empty, /// null is returned. Otherwise, either a new list is created (if /// is null) or the elements of are added to . /// private static List AddAll(List current, IList extras) { if (extras.Count == 0) { return current; } if (current == null) { current = new List(extras); } else { current.AddRange(extras); } return current; } /// /// Clears the contents of this builder. /// public Builder Clear() { varintList = null; fixed32List = null; fixed64List = null; lengthDelimitedList = null; groupList = null; return this; } /// /// Adds a varint value. /// public Builder AddVarint(ulong value) { varintList = Add(varintList, value); return this; } /// /// Adds a fixed32 value. /// public Builder AddFixed32(uint value) { fixed32List = Add(fixed32List, value); return this; } /// /// Adds a fixed64 value. /// public Builder AddFixed64(ulong value) { fixed64List = Add(fixed64List, value); return this; } /// /// Adds a length-delimited value. /// public Builder AddLengthDelimited(ByteString value) { lengthDelimitedList = Add(lengthDelimitedList, value); return this; } /// /// Adds an embedded group. /// /// /// public Builder AddGroup(UnknownFieldSet value) { groupList = Add(groupList, value); return this; } /// /// Adds to the , creating /// a new list if is null. The list is returned - either /// the original reference or the new list. /// private static List Add(List list, T value) { if (list == null) { list = new List(); } list.Add(value); return list; } /// /// Returns a read-only version of the given IList, and clears /// the field used for . If the value /// is null, an empty list is produced using Lists.Empty. /// /// private static ReadOnlyCollection MakeReadOnly(ref List list) { ReadOnlyCollection ret = list == null ? Lists.Empty : new ReadOnlyCollection(list); list = null; return ret; } } } }