#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;
}
}
}