#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2017 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // 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.Collections.ObjectModel; using Google.Protobuf.Collections; namespace Google.Protobuf { /// /// Represents a single field in an UnknownFieldSet. /// /// An UnknownField consists of four lists of values. The lists correspond /// to the four "wire types" used in the protocol buffer binary format. /// Normally, only one of the four 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. /// /// internal sealed class UnknownField { private List varintList; private List fixed32List; private List fixed64List; private List lengthDelimitedList; private List groupList; /// /// Creates a new UnknownField. /// public UnknownField() { } /// /// Checks if two unknown field are equal. /// public override bool Equals(object other) { if (ReferenceEquals(this, other)) { return true; } UnknownField otherField = other as UnknownField; return otherField != null && Lists.Equals(varintList, otherField.varintList) && Lists.Equals(fixed32List, otherField.fixed32List) && Lists.Equals(fixed64List, otherField.fixed64List) && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList) && Lists.Equals(groupList, otherField.groupList); } /// /// Get the hash code of the unknown field. /// public override int GetHashCode() { int hash = 43; hash = hash * 47 + Lists.GetHashCode(varintList); hash = hash * 47 + Lists.GetHashCode(fixed32List); hash = hash * 47 + Lists.GetHashCode(fixed64List); hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList); hash = hash * 47 + Lists.GetHashCode(groupList); return hash; } /// /// Serializes the field, including the field number, and writes it to /// /// /// The unknown field number. /// The write context to write to. internal void WriteTo(int fieldNumber, ref WriteContext output) { if (varintList != null) { foreach (ulong value in varintList) { output.WriteTag(fieldNumber, WireFormat.WireType.Varint); output.WriteUInt64(value); } } if (fixed32List != null) { foreach (uint value in fixed32List) { output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32); output.WriteFixed32(value); } } if (fixed64List != null) { foreach (ulong value in fixed64List) { output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64); output.WriteFixed64(value); } } if (lengthDelimitedList != null) { foreach (ByteString value in lengthDelimitedList) { output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); output.WriteBytes(value); } } if (groupList != null) { foreach (UnknownFieldSet value in groupList) { output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup); value.WriteTo(ref output); output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup); } } } /// /// Computes the number of bytes required to encode this field, including field /// number. /// internal int GetSerializedSize(int fieldNumber) { int result = 0; if (varintList != null) { result += CodedOutputStream.ComputeTagSize(fieldNumber) * varintList.Count; foreach (ulong value in varintList) { result += CodedOutputStream.ComputeUInt64Size(value); } } if (fixed32List != null) { result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed32List.Count; result += CodedOutputStream.ComputeFixed32Size(1) * fixed32List.Count; } if (fixed64List != null) { result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed64List.Count; result += CodedOutputStream.ComputeFixed64Size(1) * fixed64List.Count; } if (lengthDelimitedList != null) { result += CodedOutputStream.ComputeTagSize(fieldNumber) * lengthDelimitedList.Count; foreach (ByteString value in lengthDelimitedList) { result += CodedOutputStream.ComputeBytesSize(value); } } if (groupList != null) { result += CodedOutputStream.ComputeTagSize(fieldNumber) * 2 * groupList.Count; foreach (UnknownFieldSet value in groupList) { result += value.CalculateSize(); } } return result; } /// /// Merge the values in into this field. For each list /// of values, 's values are append to the ones in this /// field. /// internal UnknownField 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 null or 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 == null || extras.Count == 0) { return current; } if (current == null) { current = new List(extras); } else { current.AddRange(extras); } return current; } /// /// Adds a varint value. /// internal UnknownField AddVarint(ulong value) { varintList = Add(varintList, value); return this; } /// /// Adds a fixed32 value. /// internal UnknownField AddFixed32(uint value) { fixed32List = Add(fixed32List, value); return this; } /// /// Adds a fixed64 value. /// internal UnknownField AddFixed64(ulong value) { fixed64List = Add(fixed64List, value); return this; } /// /// Adds a length-delimited value. /// internal UnknownField AddLengthDelimited(ByteString value) { lengthDelimitedList = Add(lengthDelimitedList, value); return this; } internal UnknownField 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; } } }