• 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 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using System;
34 using System.Collections.Generic;
35 using System.Collections.ObjectModel;
36 using Google.Protobuf.Collections;
37 
38 namespace Google.Protobuf
39 {
40     /// <summary>
41     /// Represents a single field in an UnknownFieldSet.
42     ///
43     /// An UnknownField consists of four lists of values. The lists correspond
44     /// to the four "wire types" used in the protocol buffer binary format.
45     /// Normally, only one of the four lists will contain any values, since it
46     /// is impossible to define a valid message type that declares two different
47     /// types for the same field number. However, the code is designed to allow
48     /// for the case where the same unknown field number is encountered using
49     /// multiple different wire types.
50     ///
51     /// </summary>
52     internal sealed class UnknownField
53     {
54         private List<ulong> varintList;
55         private List<uint> fixed32List;
56         private List<ulong> fixed64List;
57         private List<ByteString> lengthDelimitedList;
58         private List<UnknownFieldSet> groupList;
59 
60         /// <summary>
61         /// Creates a new UnknownField.
62         /// </summary>
UnknownField()63         public UnknownField()
64         {
65         }
66 
67         /// <summary>
68         /// Checks if two unknown field are equal.
69         /// </summary>
Equals(object other)70         public override bool Equals(object other)
71         {
72             if (ReferenceEquals(this, other))
73             {
74                 return true;
75             }
76             UnknownField otherField = other as UnknownField;
77             return otherField != null
78                    && Lists.Equals(varintList, otherField.varintList)
79                    && Lists.Equals(fixed32List, otherField.fixed32List)
80                    && Lists.Equals(fixed64List, otherField.fixed64List)
81                    && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
82                    && Lists.Equals(groupList, otherField.groupList);
83         }
84 
85         /// <summary>
86         /// Get the hash code of the unknown field.
87         /// </summary>
GetHashCode()88         public override int GetHashCode()
89         {
90             int hash = 43;
91             hash = hash * 47 + Lists.GetHashCode(varintList);
92             hash = hash * 47 + Lists.GetHashCode(fixed32List);
93             hash = hash * 47 + Lists.GetHashCode(fixed64List);
94             hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList);
95             hash = hash * 47 + Lists.GetHashCode(groupList);
96             return hash;
97         }
98 
99         /// <summary>
100         /// Serializes the field, including the field number, and writes it to
101         /// <paramref name="output"/>
102         /// </summary>
103         /// <param name="fieldNumber">The unknown field number.</param>
104         /// <param name="output">The write context to write to.</param>
WriteTo(int fieldNumber, ref WriteContext output)105         internal void WriteTo(int fieldNumber, ref WriteContext output)
106         {
107             if (varintList != null)
108             {
109                 foreach (ulong value in varintList)
110                 {
111                     output.WriteTag(fieldNumber, WireFormat.WireType.Varint);
112                     output.WriteUInt64(value);
113                 }
114             }
115             if (fixed32List != null)
116             {
117                 foreach (uint value in fixed32List)
118                 {
119                     output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
120                     output.WriteFixed32(value);
121                 }
122             }
123             if (fixed64List != null)
124             {
125                 foreach (ulong value in fixed64List)
126                 {
127                     output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
128                     output.WriteFixed64(value);
129                 }
130             }
131             if (lengthDelimitedList != null)
132             {
133                 foreach (ByteString value in lengthDelimitedList)
134                 {
135                     output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
136                     output.WriteBytes(value);
137                 }
138             }
139             if (groupList != null)
140             {
141                 foreach (UnknownFieldSet value in groupList)
142                 {
143                     output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
144                     value.WriteTo(ref output);
145                     output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
146                 }
147             }
148         }
149 
150         /// <summary>
151         /// Computes the number of bytes required to encode this field, including field
152         /// number.
153         /// </summary>
GetSerializedSize(int fieldNumber)154         internal int GetSerializedSize(int fieldNumber)
155         {
156             int result = 0;
157             if (varintList != null)
158             {
159                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * varintList.Count;
160                 foreach (ulong value in varintList)
161                 {
162                     result += CodedOutputStream.ComputeUInt64Size(value);
163                 }
164             }
165             if (fixed32List != null)
166             {
167                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed32List.Count;
168                 result += CodedOutputStream.ComputeFixed32Size(1) * fixed32List.Count;
169             }
170             if (fixed64List != null)
171             {
172                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed64List.Count;
173                 result += CodedOutputStream.ComputeFixed64Size(1) * fixed64List.Count;
174             }
175             if (lengthDelimitedList != null)
176             {
177                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * lengthDelimitedList.Count;
178                 foreach (ByteString value in lengthDelimitedList)
179                 {
180                     result += CodedOutputStream.ComputeBytesSize(value);
181                 }
182             }
183             if (groupList != null)
184             {
185                 result += CodedOutputStream.ComputeTagSize(fieldNumber) * 2 * groupList.Count;
186                 foreach (UnknownFieldSet value in groupList)
187                 {
188                     result += value.CalculateSize();
189                 }
190             }
191             return result;
192         }
193 
194         /// <summary>
195         /// Merge the values in <paramref name="other" /> into this field.  For each list
196         /// of values, <paramref name="other"/>'s values are append to the ones in this
197         /// field.
198         /// </summary>
MergeFrom(UnknownField other)199         internal UnknownField MergeFrom(UnknownField other)
200         {
201             varintList = AddAll(varintList, other.varintList);
202             fixed32List = AddAll(fixed32List, other.fixed32List);
203             fixed64List = AddAll(fixed64List, other.fixed64List);
204             lengthDelimitedList = AddAll(lengthDelimitedList, other.lengthDelimitedList);
205             groupList = AddAll(groupList, other.groupList);
206             return this;
207         }
208 
209         /// <summary>
210         /// Returns a new list containing all of the given specified values from
211         /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
212         /// If <paramref name="current" /> is null and <paramref name="extras"/> is null or empty,
213         /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
214         /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
215         /// </summary>
AddAll(List<T> current, IList<T> extras)216         private static List<T> AddAll<T>(List<T> current, IList<T> extras)
217         {
218             if (extras == null || extras.Count == 0)
219             {
220                 return current;
221             }
222             if (current == null)
223             {
224                 current = new List<T>(extras);
225             }
226             else
227             {
228                 current.AddRange(extras);
229             }
230             return current;
231         }
232 
233         /// <summary>
234         /// Adds a varint value.
235         /// </summary>
AddVarint(ulong value)236         internal UnknownField AddVarint(ulong value)
237         {
238             varintList = Add(varintList, value);
239             return this;
240         }
241 
242         /// <summary>
243         /// Adds a fixed32 value.
244         /// </summary>
AddFixed32(uint value)245         internal UnknownField AddFixed32(uint value)
246         {
247             fixed32List = Add(fixed32List, value);
248             return this;
249         }
250 
251         /// <summary>
252         /// Adds a fixed64 value.
253         /// </summary>
AddFixed64(ulong value)254         internal UnknownField AddFixed64(ulong value)
255         {
256             fixed64List = Add(fixed64List, value);
257             return this;
258         }
259 
260         /// <summary>
261         /// Adds a length-delimited value.
262         /// </summary>
AddLengthDelimited(ByteString value)263         internal UnknownField AddLengthDelimited(ByteString value)
264         {
265             lengthDelimitedList = Add(lengthDelimitedList, value);
266             return this;
267         }
268 
AddGroup(UnknownFieldSet value)269         internal UnknownField AddGroup(UnknownFieldSet value)
270         {
271             groupList = Add(groupList, value);
272             return this;
273         }
274 
275         /// <summary>
276         /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
277         /// a new list if <paramref name="list"/> is null. The list is returned - either
278         /// the original reference or the new list.
279         /// </summary>
Add(List<T> list, T value)280         private static List<T> Add<T>(List<T> list, T value)
281         {
282             if (list == null)
283             {
284                 list = new List<T>();
285             }
286             list.Add(value);
287             return list;
288         }
289     }
290 }
291