UnknownField.cs 10 KB

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