• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2017 Google Inc.  All rights reserved.
4 //
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file or at
7 // https://developers.google.com/open-source/licenses/bsd
8 #endregion
9 
10 using System.Collections.Generic;
11 using Google.Protobuf.Collections;
12 
13 namespace Google.Protobuf
14 {
15     /// <summary>
16     /// Represents a single field in an UnknownFieldSet.
17     ///
18     /// An UnknownField consists of four lists of values. The lists correspond
19     /// to the four "wire types" used in the protocol buffer binary format.
20     /// Normally, only one of the four lists will contain any values, since it
21     /// is impossible to define a valid message type that declares two different
22     /// types for the same field number. However, the code is designed to allow
23     /// for the case where the same unknown field number is encountered using
24     /// multiple different wire types.
25     ///
26     /// </summary>
27     internal sealed class UnknownField
28     {
29         private List<ulong> varintList;
30         private List<uint> fixed32List;
31         private List<ulong> fixed64List;
32         private List<ByteString> lengthDelimitedList;
33         private List<UnknownFieldSet> groupList;
34 
35         /// <summary>
36         /// Creates a new UnknownField.
37         /// </summary>
UnknownField()38         public UnknownField()
39         {
40         }
41 
42         /// <summary>
43         /// Checks if two unknown field are equal.
44         /// </summary>
Equals(object other)45         public override bool Equals(object other)
46         {
47             if (ReferenceEquals(this, other))
48             {
49                 return true;
50             }
51             return other is UnknownField otherField
52                 && Lists.Equals(varintList, otherField.varintList)
53                 && Lists.Equals(fixed32List, otherField.fixed32List)
54                 && Lists.Equals(fixed64List, otherField.fixed64List)
55                 && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
56                 && Lists.Equals(groupList, otherField.groupList);
57         }
58 
59         /// <summary>
60         /// Get the hash code of the unknown field.
61         /// </summary>
GetHashCode()62         public override int GetHashCode()
63         {
64             int hash = 43;
65             hash = hash * 47 + Lists.GetHashCode(varintList);
66             hash = hash * 47 + Lists.GetHashCode(fixed32List);
67             hash = hash * 47 + Lists.GetHashCode(fixed64List);
68             hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList);
69             hash = hash * 47 + Lists.GetHashCode(groupList);
70             return hash;
71         }
72 
73         /// <summary>
74         /// Serializes the field, including the field number, and writes it to
75         /// <paramref name="output"/>
76         /// </summary>
77         /// <param name="fieldNumber">The unknown field number.</param>
78         /// <param name="output">The write context to write to.</param>
WriteTo(int fieldNumber, ref WriteContext output)79         internal void WriteTo(int fieldNumber, ref WriteContext output)
80         {
81             if (varintList != null)
82             {
83                 foreach (ulong value in varintList)
84                 {
85                     output.WriteTag(fieldNumber, WireFormat.WireType.Varint);
86                     output.WriteUInt64(value);
87                 }
88             }
89             if (fixed32List != null)
90             {
91                 foreach (uint value in fixed32List)
92                 {
93                     output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
94                     output.WriteFixed32(value);
95                 }
96             }
97             if (fixed64List != null)
98             {
99                 foreach (ulong value in fixed64List)
100                 {
101                     output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
102                     output.WriteFixed64(value);
103                 }
104             }
105             if (lengthDelimitedList != null)
106             {
107                 foreach (ByteString value in lengthDelimitedList)
108                 {
109                     output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
110                     output.WriteBytes(value);
111                 }
112             }
113             if (groupList != null)
114             {
115                 foreach (UnknownFieldSet value in groupList)
116                 {
117                     output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
118                     value.WriteTo(ref output);
119                     output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
120                 }
121             }
122         }
123 
124         /// <summary>
125         /// Computes the number of bytes required to encode this field, including field
126         /// number.
127         /// </summary>
GetSerializedSize(int fieldNumber)128         internal int GetSerializedSize(int fieldNumber)
129         {
130             int result = 0;
131             if (varintList != null)
132             {
133                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * varintList.Count;
134                 foreach (ulong value in varintList)
135                 {
136                     result += CodedOutputStream.ComputeUInt64Size(value);
137                 }
138             }
139             if (fixed32List != null)
140             {
141                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed32List.Count;
142                 result += CodedOutputStream.ComputeFixed32Size(1) * fixed32List.Count;
143             }
144             if (fixed64List != null)
145             {
146                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed64List.Count;
147                 result += CodedOutputStream.ComputeFixed64Size(1) * fixed64List.Count;
148             }
149             if (lengthDelimitedList != null)
150             {
151                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * lengthDelimitedList.Count;
152                 foreach (ByteString value in lengthDelimitedList)
153                 {
154                     result += CodedOutputStream.ComputeBytesSize(value);
155                 }
156             }
157             if (groupList != null)
158             {
159                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * 2 * groupList.Count;
160                 foreach (UnknownFieldSet value in groupList)
161                 {
162                     result += value.CalculateSize();
163                 }
164             }
165             return result;
166         }
167 
168         /// <summary>
169         /// Merge the values in <paramref name="other" /> into this field.  For each list
170         /// of values, <paramref name="other"/>'s values are append to the ones in this
171         /// field.
172         /// </summary>
MergeFrom(UnknownField other)173         internal UnknownField MergeFrom(UnknownField other)
174         {
175             varintList = AddAll(varintList, other.varintList);
176             fixed32List = AddAll(fixed32List, other.fixed32List);
177             fixed64List = AddAll(fixed64List, other.fixed64List);
178             lengthDelimitedList = AddAll(lengthDelimitedList, other.lengthDelimitedList);
179             groupList = AddAll(groupList, other.groupList);
180             return this;
181         }
182 
183         /// <summary>
184         /// Returns a new list containing all of the given specified values from
185         /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
186         /// If <paramref name="current" /> is null and <paramref name="extras"/> is null or empty,
187         /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
188         /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
189         /// </summary>
AddAll(List<T> current, IList<T> extras)190         private static List<T> AddAll<T>(List<T> current, IList<T> extras)
191         {
192             if (extras == null || extras.Count == 0)
193             {
194                 return current;
195             }
196             if (current == null)
197             {
198                 current = new List<T>(extras);
199             }
200             else
201             {
202                 current.AddRange(extras);
203             }
204             return current;
205         }
206 
207         /// <summary>
208         /// Adds a varint value.
209         /// </summary>
AddVarint(ulong value)210         internal UnknownField AddVarint(ulong value)
211         {
212             varintList = Add(varintList, value);
213             return this;
214         }
215 
216         /// <summary>
217         /// Adds a fixed32 value.
218         /// </summary>
AddFixed32(uint value)219         internal UnknownField AddFixed32(uint value)
220         {
221             fixed32List = Add(fixed32List, value);
222             return this;
223         }
224 
225         /// <summary>
226         /// Adds a fixed64 value.
227         /// </summary>
AddFixed64(ulong value)228         internal UnknownField AddFixed64(ulong value)
229         {
230             fixed64List = Add(fixed64List, value);
231             return this;
232         }
233 
234         /// <summary>
235         /// Adds a length-delimited value.
236         /// </summary>
AddLengthDelimited(ByteString value)237         internal UnknownField AddLengthDelimited(ByteString value)
238         {
239             lengthDelimitedList = Add(lengthDelimitedList, value);
240             return this;
241         }
242 
AddGroup(UnknownFieldSet value)243         internal UnknownField AddGroup(UnknownFieldSet value)
244         {
245             groupList = Add(groupList, value);
246             return this;
247         }
248 
249         /// <summary>
250         /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
251         /// a new list if <paramref name="list"/> is null. The list is returned - either
252         /// the original reference or the new list.
253         /// </summary>
Add(List<T> list, T value)254         private static List<T> Add<T>(List<T> list, T value)
255         {
256             if (list == null)
257             {
258                 list = new List<T>();
259             }
260             list.Add(value);
261             return list;
262         }
263     }
264 }
265