UnknownField.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using Google.ProtocolBuffers.Collections;
  19. namespace Google.ProtocolBuffers {
  20. /// <summary>
  21. /// Represents a single field in an UnknownFieldSet.
  22. ///
  23. /// An UnknownField consists of five lists of values. The lists correspond
  24. /// to the five "wire types" used in the protocol buffer binary format.
  25. /// The wire type of each field can be determined from the encoded form alone,
  26. /// without knowing the field's declared type. So, we are able to parse
  27. /// unknown values at least this far and separate them. Normally, only one
  28. /// of the five lists will contain any values, since it is impossible to
  29. /// define a valid message type that declares two different types for the
  30. /// same field number. However, the code is designed to allow for the case
  31. /// where the same unknown field number is encountered using multiple different
  32. /// wire types.
  33. ///
  34. /// UnknownField is an immutable class. To construct one, you must use an
  35. /// UnknownField.Builder.
  36. /// </summary>
  37. public sealed class UnknownField {
  38. private static readonly UnknownField defaultInstance = CreateBuilder().Build();
  39. private readonly ReadOnlyCollection<ulong> varintList;
  40. private readonly ReadOnlyCollection<uint> fixed32List;
  41. private readonly ReadOnlyCollection<ulong> fixed64List;
  42. private readonly ReadOnlyCollection<ByteString> lengthDelimitedList;
  43. private readonly ReadOnlyCollection<UnknownFieldSet> groupList;
  44. private UnknownField(ReadOnlyCollection<ulong> varintList,
  45. ReadOnlyCollection<uint> fixed32List,
  46. ReadOnlyCollection<ulong> fixed64List,
  47. ReadOnlyCollection<ByteString> lengthDelimitedList,
  48. ReadOnlyCollection<UnknownFieldSet> groupList) {
  49. this.varintList = varintList;
  50. this.fixed32List = fixed32List;
  51. this.fixed64List = fixed64List;
  52. this.lengthDelimitedList = lengthDelimitedList;
  53. this.groupList = groupList;
  54. }
  55. public static UnknownField DefaultInstance {
  56. get { return defaultInstance; }
  57. }
  58. /// <summary>
  59. /// The list of varint values for this field.
  60. /// </summary>
  61. public IList<ulong> VarintList {
  62. get { return varintList; }
  63. }
  64. /// <summary>
  65. /// The list of fixed32 values for this field.
  66. /// </summary>
  67. public IList<uint> Fixed32List {
  68. get { return fixed32List; }
  69. }
  70. /// <summary>
  71. /// The list of fixed64 values for this field.
  72. /// </summary>
  73. public IList<ulong> Fixed64List {
  74. get { return fixed64List; }
  75. }
  76. /// <summary>
  77. /// The list of length-delimited values for this field.
  78. /// </summary>
  79. public IList<ByteString> LengthDelimitedList {
  80. get { return lengthDelimitedList; }
  81. }
  82. /// <summary>
  83. /// The list of embedded group values for this field. These
  84. /// are represented using UnknownFieldSets rather than Messages
  85. /// since the group's type is presumably unknown.
  86. /// </summary>
  87. public IList<UnknownFieldSet> GroupList {
  88. get { return groupList; }
  89. }
  90. /// <summary>
  91. /// Constructs a new Builder.
  92. /// </summary>
  93. public static Builder CreateBuilder() {
  94. return new Builder();
  95. }
  96. /// <summary>
  97. /// Constructs a new Builder and initializes it to a copy of <paramref name="copyFrom"/>.
  98. /// </summary>
  99. public static Builder CreateBuilder(UnknownField copyFrom) {
  100. return new Builder().MergeFrom(copyFrom);
  101. }
  102. /// <summary>
  103. /// Serializes the field, including the field number, and writes it to
  104. /// <paramref name="output"/>.
  105. /// </summary>
  106. public void WriteTo(int fieldNumber, CodedOutputStream output) {
  107. foreach (ulong value in varintList) {
  108. output.WriteUInt64(fieldNumber, value);
  109. }
  110. foreach (uint value in fixed32List) {
  111. output.WriteFixed32(fieldNumber, value);
  112. }
  113. foreach (ulong value in fixed64List) {
  114. output.WriteFixed64(fieldNumber, value);
  115. }
  116. foreach (ByteString value in lengthDelimitedList) {
  117. output.WriteBytes(fieldNumber, value);
  118. }
  119. foreach (UnknownFieldSet value in groupList) {
  120. output.WriteUnknownGroup(fieldNumber, value);
  121. }
  122. }
  123. /// <summary>
  124. /// Computes the number of bytes required to encode this field, including field
  125. /// number.
  126. /// </summary>
  127. public int GetSerializedSize(int fieldNumber) {
  128. int result = 0;
  129. foreach (ulong value in varintList) {
  130. result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value);
  131. }
  132. foreach (uint value in fixed32List) {
  133. result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value);
  134. }
  135. foreach (ulong value in fixed64List) {
  136. result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value);
  137. }
  138. foreach (ByteString value in lengthDelimitedList) {
  139. result += CodedOutputStream.ComputeBytesSize(fieldNumber, value);
  140. }
  141. foreach (UnknownFieldSet value in groupList) {
  142. result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value);
  143. }
  144. return result;
  145. }
  146. /// <summary>
  147. /// Serializes the length-delimited values of the field, including field
  148. /// number, and writes them to <paramref name="output"/> using the MessageSet wire format.
  149. /// </summary>
  150. /// <param name="fieldNumber"></param>
  151. /// <param name="output"></param>
  152. public void WriteAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output) {
  153. foreach (ByteString value in lengthDelimitedList) {
  154. output.WriteRawMessageSetExtension(fieldNumber, value);
  155. }
  156. }
  157. /// <summary>
  158. /// Get the number of bytes required to encode this field, incuding field number,
  159. /// using the MessageSet wire format.
  160. /// </summary>
  161. public int GetSerializedSizeAsMessageSetExtension(int fieldNumber) {
  162. int result = 0;
  163. foreach (ByteString value in lengthDelimitedList) {
  164. result += CodedOutputStream.ComputeRawMessageSetExtensionSize(fieldNumber, value);
  165. }
  166. return result;
  167. }
  168. /// <summary>
  169. /// Used to build instances of UnknownField.
  170. /// </summary>
  171. public sealed class Builder {
  172. private List<ulong> varintList;
  173. private List<uint> fixed32List;
  174. private List<ulong> fixed64List;
  175. private List<ByteString> lengthDelimitedList;
  176. private List<UnknownFieldSet> groupList;
  177. /// <summary>
  178. /// Builds the field. After building, the builder is reset to an empty
  179. /// state. (This is actually easier than making it unusable.)
  180. /// </summary>
  181. public UnknownField Build() {
  182. return new UnknownField(MakeReadOnly(ref varintList),
  183. MakeReadOnly(ref fixed32List),
  184. MakeReadOnly(ref fixed64List),
  185. MakeReadOnly(ref lengthDelimitedList),
  186. MakeReadOnly(ref groupList));
  187. }
  188. /// <summary>
  189. /// Merge the values in <paramref name="other" /> into this field. For each list
  190. /// of values, <paramref name="other"/>'s values are append to the ones in this
  191. /// field.
  192. /// </summary>
  193. public Builder MergeFrom(UnknownField other) {
  194. varintList = AddAll(varintList, other.VarintList);
  195. fixed32List = AddAll(fixed32List, other.Fixed32List);
  196. fixed64List = AddAll(fixed64List, other.Fixed64List);
  197. lengthDelimitedList = AddAll(lengthDelimitedList, other.LengthDelimitedList);
  198. groupList = AddAll(groupList, other.GroupList);
  199. return this;
  200. }
  201. /// <summary>
  202. /// Returns a new list containing all of the given specified values from
  203. /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
  204. /// If <paramref name="current" /> is null and <paramref name="extras"/> is empty,
  205. /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
  206. /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
  207. /// </summary>
  208. private static List<T> AddAll<T>(List<T> current, IList<T> extras)
  209. {
  210. if (extras.Count == 0) {
  211. return current;
  212. }
  213. if (current == null) {
  214. current = new List<T>(extras);
  215. } else {
  216. current.AddRange(extras);
  217. }
  218. return current;
  219. }
  220. /// <summary>
  221. /// Clears the contents of this builder.
  222. /// </summary>
  223. public Builder Clear() {
  224. varintList = null;
  225. fixed32List = null;
  226. fixed64List = null;
  227. lengthDelimitedList = null;
  228. groupList = null;
  229. return this;
  230. }
  231. /// <summary>
  232. /// Adds a varint value.
  233. /// </summary>
  234. public Builder AddVarint(ulong value) {
  235. varintList = Add(varintList, value);
  236. return this;
  237. }
  238. /// <summary>
  239. /// Adds a fixed32 value.
  240. /// </summary>
  241. public Builder AddFixed32(uint value) {
  242. fixed32List = Add(fixed32List, value);
  243. return this;
  244. }
  245. /// <summary>
  246. /// Adds a fixed64 value.
  247. /// </summary>
  248. public Builder AddFixed64(ulong value) {
  249. fixed64List = Add(fixed64List, value);
  250. return this;
  251. }
  252. /// <summary>
  253. /// Adds a length-delimited value.
  254. /// </summary>
  255. public Builder AddLengthDelimited(ByteString value) {
  256. lengthDelimitedList = Add(lengthDelimitedList, value);
  257. return this;
  258. }
  259. /// <summary>
  260. /// Adds an embedded group.
  261. /// </summary>
  262. /// <param name="value"></param>
  263. /// <returns></returns>
  264. public Builder AddGroup(UnknownFieldSet value) {
  265. groupList = Add(groupList, value);
  266. return this;
  267. }
  268. /// <summary>
  269. /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
  270. /// a new list if <paramref name="list"/> is null. The list is returned - either
  271. /// the original reference or the new list.
  272. /// </summary>
  273. private static List<T> Add<T>(List<T> list, T value) {
  274. if (list == null) {
  275. list = new List<T>();
  276. }
  277. list.Add(value);
  278. return list;
  279. }
  280. /// <summary>
  281. /// Returns a read-only version of the given IList, and clears
  282. /// the field used for <paramref name="list"/>. If the value
  283. /// is null, an empty list is produced using Lists.Empty.
  284. /// </summary>
  285. /// <returns></returns>
  286. private static ReadOnlyCollection<T> MakeReadOnly<T>(ref List<T> list) {
  287. ReadOnlyCollection<T> ret = list == null ? Lists<T>.Empty : new ReadOnlyCollection<T>(list);
  288. list = null;
  289. return ret;
  290. }
  291. }
  292. }
  293. }