#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2017 Google Inc. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #endregion using System.Collections.Generic; 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; } return other is UnknownField otherField && 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; } } }