blob: c403e8a98c0c14f70a373ebcbaa9dbd04022bda7 [file] [log] [blame]
csharptestd965c662011-05-20 13:57:07 -05001#region Copyright notice and license
csharptest71f662c2011-05-20 15:15:34 -05002
csharptestd965c662011-05-20 13:57:07 -05003// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
csharptest71f662c2011-05-20 15:15:34 -050034
csharptestd965c662011-05-20 13:57:07 -050035#endregion
36
37using System;
38using System.Collections.Generic;
39using System.Collections.ObjectModel;
40using Google.ProtocolBuffers.Collections;
41
csharptest71f662c2011-05-20 15:15:34 -050042namespace Google.ProtocolBuffers
43{
csharptestd965c662011-05-20 13:57:07 -050044 /// <summary>
csharptest71f662c2011-05-20 15:15:34 -050045 /// Represents a single field in an UnknownFieldSet.
46 ///
47 /// An UnknownField consists of five lists of values. The lists correspond
48 /// to the five "wire types" used in the protocol buffer binary format.
49 /// The wire type of each field can be determined from the encoded form alone,
50 /// without knowing the field's declared type. So, we are able to parse
51 /// unknown values at least this far and separate them. Normally, only one
52 /// of the five lists will contain any values, since it is impossible to
53 /// define a valid message type that declares two different types for the
54 /// same field number. However, the code is designed to allow for the case
55 /// where the same unknown field number is encountered using multiple different
56 /// wire types.
57 ///
58 /// UnknownField is an immutable class. To construct one, you must use an
59 /// UnknownField.Builder.
csharptestd965c662011-05-20 13:57:07 -050060 /// </summary>
csharptest71f662c2011-05-20 15:15:34 -050061 public sealed class UnknownField
62 {
63 private static readonly UnknownField defaultInstance = CreateBuilder().Build();
64 private readonly ReadOnlyCollection<ulong> varintList;
65 private readonly ReadOnlyCollection<uint> fixed32List;
66 private readonly ReadOnlyCollection<ulong> fixed64List;
67 private readonly ReadOnlyCollection<ByteString> lengthDelimitedList;
68 private readonly ReadOnlyCollection<UnknownFieldSet> groupList;
csharptestd965c662011-05-20 13:57:07 -050069
csharptest71f662c2011-05-20 15:15:34 -050070 private UnknownField(ReadOnlyCollection<ulong> varintList,
71 ReadOnlyCollection<uint> fixed32List,
72 ReadOnlyCollection<ulong> fixed64List,
73 ReadOnlyCollection<ByteString> lengthDelimitedList,
74 ReadOnlyCollection<UnknownFieldSet> groupList)
75 {
76 this.varintList = varintList;
77 this.fixed32List = fixed32List;
78 this.fixed64List = fixed64List;
79 this.lengthDelimitedList = lengthDelimitedList;
80 this.groupList = groupList;
81 }
csharptestd965c662011-05-20 13:57:07 -050082
csharptest71f662c2011-05-20 15:15:34 -050083 public static UnknownField DefaultInstance
84 {
85 get { return defaultInstance; }
86 }
csharptestd965c662011-05-20 13:57:07 -050087
csharptest71f662c2011-05-20 15:15:34 -050088 /// <summary>
89 /// The list of varint values for this field.
90 /// </summary>
91 public IList<ulong> VarintList
92 {
93 get { return varintList; }
94 }
csharptestd965c662011-05-20 13:57:07 -050095
csharptest71f662c2011-05-20 15:15:34 -050096 /// <summary>
97 /// The list of fixed32 values for this field.
98 /// </summary>
99 public IList<uint> Fixed32List
100 {
101 get { return fixed32List; }
102 }
csharptestd965c662011-05-20 13:57:07 -0500103
csharptest71f662c2011-05-20 15:15:34 -0500104 /// <summary>
105 /// The list of fixed64 values for this field.
106 /// </summary>
107 public IList<ulong> Fixed64List
108 {
109 get { return fixed64List; }
110 }
csharptestd965c662011-05-20 13:57:07 -0500111
csharptest71f662c2011-05-20 15:15:34 -0500112 /// <summary>
113 /// The list of length-delimited values for this field.
114 /// </summary>
115 public IList<ByteString> LengthDelimitedList
116 {
117 get { return lengthDelimitedList; }
118 }
csharptestd965c662011-05-20 13:57:07 -0500119
csharptest71f662c2011-05-20 15:15:34 -0500120 /// <summary>
121 /// The list of embedded group values for this field. These
122 /// are represented using UnknownFieldSets rather than Messages
123 /// since the group's type is presumably unknown.
124 /// </summary>
125 public IList<UnknownFieldSet> GroupList
126 {
127 get { return groupList; }
128 }
csharptestd965c662011-05-20 13:57:07 -0500129
csharptest71f662c2011-05-20 15:15:34 -0500130 public override bool Equals(object other)
131 {
132 if (ReferenceEquals(this, other))
133 {
134 return true;
135 }
136 UnknownField otherField = other as UnknownField;
137 return otherField != null
138 && Lists.Equals(varintList, otherField.varintList)
139 && Lists.Equals(fixed32List, otherField.fixed32List)
140 && Lists.Equals(fixed64List, otherField.fixed64List)
141 && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
142 && Lists.Equals(groupList, otherField.groupList);
143 }
144
145 public override int GetHashCode()
146 {
147 int hash = 43;
148 hash = hash*47 + Lists.GetHashCode(varintList);
149 hash = hash*47 + Lists.GetHashCode(fixed32List);
150 hash = hash*47 + Lists.GetHashCode(fixed64List);
151 hash = hash*47 + Lists.GetHashCode(lengthDelimitedList);
152 hash = hash*47 + Lists.GetHashCode(groupList);
153 return hash;
154 }
155
156 /// <summary>
157 /// Constructs a new Builder.
158 /// </summary>
159 public static Builder CreateBuilder()
160 {
161 return new Builder();
162 }
163
164 /// <summary>
165 /// Constructs a new Builder and initializes it to a copy of <paramref name="copyFrom"/>.
166 /// </summary>
167 public static Builder CreateBuilder(UnknownField copyFrom)
168 {
169 return new Builder().MergeFrom(copyFrom);
170 }
171
172 /// <summary>
173 /// Serializes the field, including the field number, and writes it to
174 /// <paramref name="output"/>.
175 /// </summary>
176 public void WriteTo(int fieldNumber, CodedOutputStream output)
177 {
178 foreach (ulong value in varintList)
179 {
180 output.WriteUInt64(fieldNumber, value);
181 }
182 foreach (uint value in fixed32List)
183 {
184 output.WriteFixed32(fieldNumber, value);
185 }
186 foreach (ulong value in fixed64List)
187 {
188 output.WriteFixed64(fieldNumber, value);
189 }
190 foreach (ByteString value in lengthDelimitedList)
191 {
192 output.WriteBytes(fieldNumber, value);
193 }
194 foreach (UnknownFieldSet value in groupList)
195 {
csharptestd965c662011-05-20 13:57:07 -0500196#pragma warning disable 0612
csharptest71f662c2011-05-20 15:15:34 -0500197 output.WriteUnknownGroup(fieldNumber, value);
csharptestd965c662011-05-20 13:57:07 -0500198#pragma warning restore 0612
csharptest71f662c2011-05-20 15:15:34 -0500199 }
200 }
csharptestd965c662011-05-20 13:57:07 -0500201
csharptest71f662c2011-05-20 15:15:34 -0500202 /// <summary>
203 /// Computes the number of bytes required to encode this field, including field
204 /// number.
205 /// </summary>
206 public int GetSerializedSize(int fieldNumber)
207 {
208 int result = 0;
209 foreach (ulong value in varintList)
210 {
211 result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value);
212 }
213 foreach (uint value in fixed32List)
214 {
215 result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value);
216 }
217 foreach (ulong value in fixed64List)
218 {
219 result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value);
220 }
221 foreach (ByteString value in lengthDelimitedList)
222 {
223 result += CodedOutputStream.ComputeBytesSize(fieldNumber, value);
224 }
225 foreach (UnknownFieldSet value in groupList)
226 {
csharptestd965c662011-05-20 13:57:07 -0500227#pragma warning disable 0612
csharptest71f662c2011-05-20 15:15:34 -0500228 result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value);
csharptestd965c662011-05-20 13:57:07 -0500229#pragma warning restore 0612
csharptest71f662c2011-05-20 15:15:34 -0500230 }
231 return result;
csharptestd965c662011-05-20 13:57:07 -0500232 }
csharptest71f662c2011-05-20 15:15:34 -0500233
234 /// <summary>
235 /// Serializes the length-delimited values of the field, including field
236 /// number, and writes them to <paramref name="output"/> using the MessageSet wire format.
237 /// </summary>
238 /// <param name="fieldNumber"></param>
239 /// <param name="output"></param>
240 public void WriteAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output)
241 {
242 foreach (ByteString value in lengthDelimitedList)
243 {
244 output.WriteRawMessageSetExtension(fieldNumber, value);
245 }
csharptestd965c662011-05-20 13:57:07 -0500246 }
csharptestd965c662011-05-20 13:57:07 -0500247
csharptest71f662c2011-05-20 15:15:34 -0500248 /// <summary>
249 /// Get the number of bytes required to encode this field, incuding field number,
250 /// using the MessageSet wire format.
251 /// </summary>
252 public int GetSerializedSizeAsMessageSetExtension(int fieldNumber)
253 {
254 int result = 0;
255 foreach (ByteString value in lengthDelimitedList)
256 {
257 result += CodedOutputStream.ComputeRawMessageSetExtensionSize(fieldNumber, value);
258 }
259 return result;
csharptestd965c662011-05-20 13:57:07 -0500260 }
csharptestd965c662011-05-20 13:57:07 -0500261
csharptest71f662c2011-05-20 15:15:34 -0500262 /// <summary>
263 /// Used to build instances of UnknownField.
264 /// </summary>
265 public sealed class Builder
266 {
267 private List<ulong> varintList;
268 private List<uint> fixed32List;
269 private List<ulong> fixed64List;
270 private List<ByteString> lengthDelimitedList;
271 private List<UnknownFieldSet> groupList;
272
273 /// <summary>
274 /// Builds the field. After building, the builder is reset to an empty
275 /// state. (This is actually easier than making it unusable.)
276 /// </summary>
277 public UnknownField Build()
278 {
279 return new UnknownField(MakeReadOnly(ref varintList),
280 MakeReadOnly(ref fixed32List),
281 MakeReadOnly(ref fixed64List),
282 MakeReadOnly(ref lengthDelimitedList),
283 MakeReadOnly(ref groupList));
284 }
285
286 /// <summary>
287 /// Merge the values in <paramref name="other" /> into this field. For each list
288 /// of values, <paramref name="other"/>'s values are append to the ones in this
289 /// field.
290 /// </summary>
291 public Builder MergeFrom(UnknownField other)
292 {
293 varintList = AddAll(varintList, other.VarintList);
294 fixed32List = AddAll(fixed32List, other.Fixed32List);
295 fixed64List = AddAll(fixed64List, other.Fixed64List);
296 lengthDelimitedList = AddAll(lengthDelimitedList, other.LengthDelimitedList);
297 groupList = AddAll(groupList, other.GroupList);
298 return this;
299 }
300
301 /// <summary>
302 /// Returns a new list containing all of the given specified values from
303 /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
304 /// If <paramref name="current" /> is null and <paramref name="extras"/> is empty,
305 /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
306 /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
307 /// </summary>
308 private static List<T> AddAll<T>(List<T> current, IList<T> extras)
309 {
310 if (extras.Count == 0)
311 {
312 return current;
313 }
314 if (current == null)
315 {
316 current = new List<T>(extras);
317 }
318 else
319 {
320 current.AddRange(extras);
321 }
322 return current;
323 }
324
325 /// <summary>
326 /// Clears the contents of this builder.
327 /// </summary>
328 public Builder Clear()
329 {
330 varintList = null;
331 fixed32List = null;
332 fixed64List = null;
333 lengthDelimitedList = null;
334 groupList = null;
335 return this;
336 }
337
338 /// <summary>
339 /// Adds a varint value.
340 /// </summary>
341 [CLSCompliant(false)]
342 public Builder AddVarint(ulong value)
343 {
344 varintList = Add(varintList, value);
345 return this;
346 }
347
348 /// <summary>
349 /// Adds a fixed32 value.
350 /// </summary>
351 [CLSCompliant(false)]
352 public Builder AddFixed32(uint value)
353 {
354 fixed32List = Add(fixed32List, value);
355 return this;
356 }
357
358 /// <summary>
359 /// Adds a fixed64 value.
360 /// </summary>
361 [CLSCompliant(false)]
362 public Builder AddFixed64(ulong value)
363 {
364 fixed64List = Add(fixed64List, value);
365 return this;
366 }
367
368 /// <summary>
369 /// Adds a length-delimited value.
370 /// </summary>
371 public Builder AddLengthDelimited(ByteString value)
372 {
373 lengthDelimitedList = Add(lengthDelimitedList, value);
374 return this;
375 }
376
377 /// <summary>
378 /// Adds an embedded group.
379 /// </summary>
380 /// <param name="value"></param>
381 /// <returns></returns>
382 public Builder AddGroup(UnknownFieldSet value)
383 {
384 groupList = Add(groupList, value);
385 return this;
386 }
387
388 /// <summary>
389 /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
390 /// a new list if <paramref name="list"/> is null. The list is returned - either
391 /// the original reference or the new list.
392 /// </summary>
393 private static List<T> Add<T>(List<T> list, T value)
394 {
395 if (list == null)
396 {
397 list = new List<T>();
398 }
399 list.Add(value);
400 return list;
401 }
402
403 /// <summary>
404 /// Returns a read-only version of the given IList, and clears
405 /// the field used for <paramref name="list"/>. If the value
406 /// is null, an empty list is produced using Lists.Empty.
407 /// </summary>
408 /// <returns></returns>
409 private static ReadOnlyCollection<T> MakeReadOnly<T>(ref List<T> list)
410 {
411 ReadOnlyCollection<T> ret = list == null ? Lists<T>.Empty : new ReadOnlyCollection<T>(list);
412 list = null;
413 return ret;
414 }
415 }
csharptestd965c662011-05-20 13:57:07 -0500416 }
csharptest71f662c2011-05-20 15:15:34 -0500417}