UnknownFieldSet.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using System.Collections.Generic;
  36. using System.IO;
  37. using Google.ProtocolBuffers.Collections;
  38. using Google.ProtocolBuffers.Descriptors;
  39. using Google.ProtocolBuffers.DescriptorProtos;
  40. namespace Google.ProtocolBuffers
  41. {
  42. /// <summary>
  43. /// Used to keep track of fields which were seen when parsing a protocol message
  44. /// but whose field numbers or types are unrecognized. This most frequently
  45. /// occurs when new fields are added to a message type and then messages containing
  46. /// those fields are read by old software that was built before the new types were
  47. /// added.
  48. ///
  49. /// Every message contains an UnknownFieldSet.
  50. ///
  51. /// Most users will never need to use this class directly.
  52. /// </summary>
  53. public sealed class UnknownFieldSet : IMessageLite
  54. {
  55. private static readonly UnknownFieldSet defaultInstance =
  56. new UnknownFieldSet(new Dictionary<int, UnknownField>());
  57. private readonly IDictionary<int, UnknownField> fields;
  58. private UnknownFieldSet(IDictionary<int, UnknownField> fields)
  59. {
  60. this.fields = fields;
  61. }
  62. /// <summary>
  63. /// Creates a new unknown field set builder.
  64. /// </summary>
  65. public static Builder CreateBuilder()
  66. {
  67. return new Builder();
  68. }
  69. /// <summary>
  70. /// Creates a new unknown field set builder
  71. /// and initialize it from <paramref name="original"/>.
  72. /// </summary>
  73. public static Builder CreateBuilder(UnknownFieldSet original)
  74. {
  75. return new Builder().MergeFrom(original);
  76. }
  77. public static UnknownFieldSet DefaultInstance
  78. {
  79. get { return defaultInstance; }
  80. }
  81. /// <summary>
  82. /// Returns a read-only view of the mapping from field numbers to values.
  83. /// </summary>
  84. public IDictionary<int, UnknownField> FieldDictionary
  85. {
  86. get { return Dictionaries.AsReadOnly(fields); }
  87. }
  88. /// <summary>
  89. /// Checks whether or not the given field number is present in the set.
  90. /// </summary>
  91. public bool HasField(int field)
  92. {
  93. return fields.ContainsKey(field);
  94. }
  95. /// <summary>
  96. /// Fetches a field by number, returning an empty field if not present.
  97. /// Never returns null.
  98. /// </summary>
  99. public UnknownField this[int number]
  100. {
  101. get
  102. {
  103. UnknownField ret;
  104. if (!fields.TryGetValue(number, out ret))
  105. {
  106. ret = UnknownField.DefaultInstance;
  107. }
  108. return ret;
  109. }
  110. }
  111. /// <summary>
  112. /// Serializes the set and writes it to <paramref name="output"/>.
  113. /// </summary>
  114. public void WriteTo(ICodedOutputStream output)
  115. {
  116. foreach (KeyValuePair<int, UnknownField> entry in fields)
  117. {
  118. entry.Value.WriteTo(entry.Key, output);
  119. }
  120. }
  121. /// <summary>
  122. /// Gets the number of bytes required to encode this set.
  123. /// </summary>
  124. public int SerializedSize
  125. {
  126. get
  127. {
  128. int result = 0;
  129. foreach (KeyValuePair<int, UnknownField> entry in fields)
  130. {
  131. result += entry.Value.GetSerializedSize(entry.Key);
  132. }
  133. return result;
  134. }
  135. }
  136. /// <summary>
  137. /// Converts the set to a string in protocol buffer text format. This
  138. /// is just a trivial wrapper around TextFormat.PrintToString.
  139. /// </summary>
  140. public override String ToString()
  141. {
  142. return TextFormat.PrintToString(this);
  143. }
  144. /// <summary>
  145. /// Converts the set to a string in protocol buffer text format. This
  146. /// is just a trivial wrapper around TextFormat.PrintToString.
  147. /// </summary>
  148. public void PrintTo(TextWriter writer)
  149. {
  150. TextFormat.Print(this, writer);
  151. }
  152. /// <summary>
  153. /// Serializes the message to a ByteString and returns it. This is
  154. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  155. /// </summary>
  156. /// <returns></returns>
  157. public ByteString ToByteString()
  158. {
  159. ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize);
  160. WriteTo(codedBuilder.CodedOutput);
  161. return codedBuilder.Build();
  162. }
  163. /// <summary>
  164. /// Serializes the message to a byte array and returns it. This is
  165. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  166. /// </summary>
  167. /// <returns></returns>
  168. public byte[] ToByteArray()
  169. {
  170. byte[] data = new byte[SerializedSize];
  171. CodedOutputStream output = CodedOutputStream.CreateInstance(data);
  172. WriteTo(output);
  173. output.CheckNoSpaceLeft();
  174. return data;
  175. }
  176. /// <summary>
  177. /// Serializes the message and writes it to <paramref name="output"/>. This is
  178. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  179. /// </summary>
  180. /// <param name="output"></param>
  181. public void WriteTo(Stream output)
  182. {
  183. CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
  184. WriteTo(codedOutput);
  185. codedOutput.Flush();
  186. }
  187. /// <summary>
  188. /// Serializes the set and writes it to <paramref name="output"/> using
  189. /// the MessageSet wire format.
  190. /// </summary>
  191. public void WriteAsMessageSetTo(ICodedOutputStream output)
  192. {
  193. foreach (KeyValuePair<int, UnknownField> entry in fields)
  194. {
  195. entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output);
  196. }
  197. }
  198. /// <summary>
  199. /// Gets the number of bytes required to encode this set using the MessageSet
  200. /// wire format.
  201. /// </summary>
  202. public int SerializedSizeAsMessageSet
  203. {
  204. get
  205. {
  206. int result = 0;
  207. foreach (KeyValuePair<int, UnknownField> entry in fields)
  208. {
  209. result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key);
  210. }
  211. return result;
  212. }
  213. }
  214. public override bool Equals(object other)
  215. {
  216. if (ReferenceEquals(this, other))
  217. {
  218. return true;
  219. }
  220. UnknownFieldSet otherSet = other as UnknownFieldSet;
  221. return otherSet != null && Dictionaries.Equals(fields, otherSet.fields);
  222. }
  223. public override int GetHashCode()
  224. {
  225. return Dictionaries.GetHashCode(fields);
  226. }
  227. /// <summary>
  228. /// Parses an UnknownFieldSet from the given input.
  229. /// </summary>
  230. public static UnknownFieldSet ParseFrom(ICodedInputStream input)
  231. {
  232. return CreateBuilder().MergeFrom(input).Build();
  233. }
  234. /// <summary>
  235. /// Parses an UnknownFieldSet from the given data.
  236. /// </summary>
  237. public static UnknownFieldSet ParseFrom(ByteString data)
  238. {
  239. return CreateBuilder().MergeFrom(data).Build();
  240. }
  241. /// <summary>
  242. /// Parses an UnknownFieldSet from the given data.
  243. /// </summary>
  244. public static UnknownFieldSet ParseFrom(byte[] data)
  245. {
  246. return CreateBuilder().MergeFrom(data).Build();
  247. }
  248. /// <summary>
  249. /// Parses an UnknownFieldSet from the given input.
  250. /// </summary>
  251. public static UnknownFieldSet ParseFrom(Stream input)
  252. {
  253. return CreateBuilder().MergeFrom(input).Build();
  254. }
  255. #region IMessageLite Members
  256. public bool IsInitialized
  257. {
  258. get { return fields != null; }
  259. }
  260. public void WriteDelimitedTo(Stream output)
  261. {
  262. CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
  263. codedOutput.WriteRawVarint32((uint) SerializedSize);
  264. WriteTo(codedOutput);
  265. codedOutput.Flush();
  266. }
  267. public IBuilderLite WeakCreateBuilderForType()
  268. {
  269. return new Builder();
  270. }
  271. public IBuilderLite WeakToBuilder()
  272. {
  273. return new Builder(fields);
  274. }
  275. public IMessageLite WeakDefaultInstanceForType
  276. {
  277. get { return defaultInstance; }
  278. }
  279. #endregion
  280. /// <summary>
  281. /// Builder for UnknownFieldSets.
  282. /// </summary>
  283. public sealed class Builder : IBuilderLite
  284. {
  285. /// <summary>
  286. /// Mapping from number to field. Note that by using a SortedList we ensure
  287. /// that the fields will be serialized in ascending order.
  288. /// </summary>
  289. private IDictionary<int, UnknownField> fields;
  290. // Optimization: We keep around a builder for the last field that was
  291. // modified so that we can efficiently add to it multiple times in a
  292. // row (important when parsing an unknown repeated field).
  293. private int lastFieldNumber;
  294. private UnknownField.Builder lastField;
  295. internal Builder()
  296. {
  297. fields = new SortedList<int, UnknownField>();
  298. }
  299. internal Builder(IDictionary<int, UnknownField> dictionary)
  300. {
  301. fields = new SortedList<int, UnknownField>(dictionary);
  302. }
  303. /// <summary>
  304. /// Returns a field builder for the specified field number, including any values
  305. /// which already exist.
  306. /// </summary>
  307. private UnknownField.Builder GetFieldBuilder(int number)
  308. {
  309. if (lastField != null)
  310. {
  311. if (number == lastFieldNumber)
  312. {
  313. return lastField;
  314. }
  315. // Note: AddField() will reset lastField and lastFieldNumber.
  316. AddField(lastFieldNumber, lastField.Build());
  317. }
  318. if (number == 0)
  319. {
  320. return null;
  321. }
  322. lastField = UnknownField.CreateBuilder();
  323. UnknownField existing;
  324. if (fields.TryGetValue(number, out existing))
  325. {
  326. lastField.MergeFrom(existing);
  327. }
  328. lastFieldNumber = number;
  329. return lastField;
  330. }
  331. /// <summary>
  332. /// Build the UnknownFieldSet and return it. Once this method has been called,
  333. /// this instance will no longer be usable. Calling any method after this
  334. /// will throw a NullReferenceException.
  335. /// </summary>
  336. public UnknownFieldSet Build()
  337. {
  338. GetFieldBuilder(0); // Force lastField to be built.
  339. UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields);
  340. fields = null;
  341. return result;
  342. }
  343. /// <summary>
  344. /// Adds a field to the set. If a field with the same number already exists, it
  345. /// is replaced.
  346. /// </summary>
  347. public Builder AddField(int number, UnknownField field)
  348. {
  349. if (number == 0)
  350. {
  351. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  352. }
  353. if (lastField != null && lastFieldNumber == number)
  354. {
  355. // Discard this.
  356. lastField = null;
  357. lastFieldNumber = 0;
  358. }
  359. fields[number] = field;
  360. return this;
  361. }
  362. /// <summary>
  363. /// Resets the builder to an empty set.
  364. /// </summary>
  365. public Builder Clear()
  366. {
  367. fields.Clear();
  368. lastFieldNumber = 0;
  369. lastField = null;
  370. return this;
  371. }
  372. /// <summary>
  373. /// Parse an entire message from <paramref name="input"/> and merge
  374. /// its fields into this set.
  375. /// </summary>
  376. public Builder MergeFrom(ICodedInputStream input)
  377. {
  378. uint tag;
  379. string name;
  380. while (input.ReadTag(out tag, out name))
  381. {
  382. if (tag == 0)
  383. {
  384. if (input.SkipField())
  385. continue; //can't merge unknown without field tag
  386. break;
  387. }
  388. if(!MergeFieldFrom(tag, input))
  389. break;
  390. }
  391. return this;
  392. }
  393. /// <summary>
  394. /// Parse a single field from <paramref name="input"/> and merge it
  395. /// into this set.
  396. /// </summary>
  397. /// <param name="tag">The field's tag number, which was already parsed.</param>
  398. /// <param name="input">The coded input stream containing the field</param>
  399. /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
  400. [CLSCompliant(false)]
  401. public bool MergeFieldFrom(uint tag, ICodedInputStream input)
  402. {
  403. int number = WireFormat.GetTagFieldNumber(tag);
  404. switch (WireFormat.GetTagWireType(tag))
  405. {
  406. case WireFormat.WireType.Varint:
  407. {
  408. ulong uint64 = 0;
  409. if(input.ReadUInt64(ref uint64))
  410. GetFieldBuilder(number).AddVarint(uint64);
  411. return true;
  412. }
  413. case WireFormat.WireType.Fixed32:
  414. {
  415. uint uint32 = 0;
  416. if (input.ReadFixed32(ref uint32))
  417. GetFieldBuilder(number).AddFixed32(uint32);
  418. return true;
  419. }
  420. case WireFormat.WireType.Fixed64:
  421. {
  422. ulong uint64 = 0;
  423. if (input.ReadFixed64(ref uint64))
  424. GetFieldBuilder(number).AddFixed64(uint64);
  425. return true;
  426. }
  427. case WireFormat.WireType.LengthDelimited:
  428. {
  429. ByteString bytes = null;
  430. if (input.ReadBytes(ref bytes))
  431. GetFieldBuilder(number).AddLengthDelimited(bytes);
  432. return true;
  433. }
  434. case WireFormat.WireType.StartGroup:
  435. {
  436. Builder subBuilder = CreateBuilder();
  437. #pragma warning disable 0612
  438. input.ReadUnknownGroup(number, subBuilder);
  439. #pragma warning restore 0612
  440. GetFieldBuilder(number).AddGroup(subBuilder.Build());
  441. return true;
  442. }
  443. case WireFormat.WireType.EndGroup:
  444. return false;
  445. default:
  446. throw InvalidProtocolBufferException.InvalidWireType();
  447. }
  448. }
  449. /// <summary>
  450. /// Parses <paramref name="input"/> as an UnknownFieldSet and merge it
  451. /// with the set being built. This is just a small wrapper around
  452. /// MergeFrom(ICodedInputStream).
  453. /// </summary>
  454. public Builder MergeFrom(Stream input)
  455. {
  456. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  457. MergeFrom(codedInput);
  458. codedInput.CheckLastTagWas(0);
  459. return this;
  460. }
  461. /// <summary>
  462. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  463. /// with the set being built. This is just a small wrapper around
  464. /// MergeFrom(ICodedInputStream).
  465. /// </summary>
  466. public Builder MergeFrom(ByteString data)
  467. {
  468. CodedInputStream input = data.CreateCodedInput();
  469. MergeFrom(input);
  470. input.CheckLastTagWas(0);
  471. return this;
  472. }
  473. /// <summary>
  474. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  475. /// with the set being built. This is just a small wrapper around
  476. /// MergeFrom(ICodedInputStream).
  477. /// </summary>
  478. public Builder MergeFrom(byte[] data)
  479. {
  480. CodedInputStream input = CodedInputStream.CreateInstance(data);
  481. MergeFrom(input);
  482. input.CheckLastTagWas(0);
  483. return this;
  484. }
  485. /// <summary>
  486. /// Convenience method for merging a new field containing a single varint
  487. /// value. This is used in particular when an unknown enum value is
  488. /// encountered.
  489. /// </summary>
  490. [CLSCompliant(false)]
  491. public Builder MergeVarintField(int number, ulong value)
  492. {
  493. if (number == 0)
  494. {
  495. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  496. }
  497. GetFieldBuilder(number).AddVarint(value);
  498. return this;
  499. }
  500. /// <summary>
  501. /// Merges the fields from <paramref name="other"/> into this set.
  502. /// If a field number exists in both sets, the values in <paramref name="other"/>
  503. /// will be appended to the values in this set.
  504. /// </summary>
  505. public Builder MergeFrom(UnknownFieldSet other)
  506. {
  507. if (other != DefaultInstance)
  508. {
  509. foreach (KeyValuePair<int, UnknownField> entry in other.fields)
  510. {
  511. MergeField(entry.Key, entry.Value);
  512. }
  513. }
  514. return this;
  515. }
  516. /// <summary>
  517. /// Checks if the given field number is present in the set.
  518. /// </summary>
  519. public bool HasField(int number)
  520. {
  521. if (number == 0)
  522. {
  523. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  524. }
  525. return number == lastFieldNumber || fields.ContainsKey(number);
  526. }
  527. /// <summary>
  528. /// Adds a field to the unknown field set. If a field with the same
  529. /// number already exists, the two are merged.
  530. /// </summary>
  531. public Builder MergeField(int number, UnknownField field)
  532. {
  533. if (number == 0)
  534. {
  535. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  536. }
  537. if (HasField(number))
  538. {
  539. GetFieldBuilder(number).MergeFrom(field);
  540. }
  541. else
  542. {
  543. // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
  544. // in this case, but that would create a copy of the Field object.
  545. // We'd rather reuse the one passed to us, so call AddField() instead.
  546. AddField(number, field);
  547. }
  548. return this;
  549. }
  550. internal void MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder)
  551. {
  552. uint tag;
  553. string name;
  554. while (input.ReadTag(out tag, out name))
  555. {
  556. if (tag == 0)
  557. {
  558. if (input.SkipField())
  559. continue; //can't merge unknown without field tag
  560. break;
  561. }
  562. if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name))
  563. {
  564. // end group tag
  565. break;
  566. }
  567. }
  568. }
  569. /// <summary>
  570. /// Like <see cref="MergeFrom(ICodedInputStream, ExtensionRegistry, IBuilder)" />
  571. /// but parses a single field.
  572. /// </summary>
  573. /// <param name="input">The input to read the field from</param>
  574. /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param>
  575. /// <param name="builder">Builder to merge field into, if it's a known field</param>
  576. /// <param name="tag">The tag, which should already have been read from the input</param>
  577. /// <returns>true unless the tag is an end-group tag</returns>
  578. internal bool MergeFieldFrom(ICodedInputStream input,
  579. ExtensionRegistry extensionRegistry, IBuilder builder, uint tag, string fieldName)
  580. {
  581. MessageDescriptor type = builder.DescriptorForType;
  582. if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart)
  583. {
  584. MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder);
  585. return true;
  586. }
  587. WireFormat.WireType wireType = WireFormat.GetTagWireType(tag);
  588. int fieldNumber = WireFormat.GetTagFieldNumber(tag);
  589. FieldDescriptor field;
  590. IMessageLite defaultFieldInstance = null;
  591. if (type.IsExtensionNumber(fieldNumber))
  592. {
  593. ExtensionInfo extension = extensionRegistry[type, fieldNumber];
  594. if (extension == null)
  595. {
  596. field = null;
  597. }
  598. else
  599. {
  600. field = extension.Descriptor;
  601. defaultFieldInstance = extension.DefaultInstance;
  602. }
  603. }
  604. else
  605. {
  606. field = type.FindFieldByNumber(fieldNumber);
  607. }
  608. // Unknown field or wrong wire type. Skip.
  609. if (field == null || wireType != WireFormat.GetWireType(field))
  610. {
  611. return MergeFieldFrom(tag, input);
  612. }
  613. switch (field.FieldType)
  614. {
  615. case FieldType.Group:
  616. case FieldType.Message:
  617. {
  618. IBuilderLite subBuilder = (defaultFieldInstance != null) ? defaultFieldInstance.WeakCreateBuilderForType() : builder.CreateBuilderForField(field);
  619. if (!field.IsRepeated)
  620. {
  621. subBuilder.WeakMergeFrom((IMessageLite)builder[field]);
  622. if (field.FieldType == FieldType.Group)
  623. input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
  624. else
  625. input.ReadMessage(subBuilder, extensionRegistry);
  626. builder[field] = subBuilder.WeakBuild();
  627. }
  628. else
  629. {
  630. List<IMessageLite> list = new List<IMessageLite>();
  631. if (field.FieldType == FieldType.Group)
  632. input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry);
  633. else
  634. input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry);
  635. foreach (IMessageLite m in list)
  636. builder.WeakAddRepeatedField(field, m);
  637. return true;
  638. }
  639. break;
  640. }
  641. case FieldType.Enum:
  642. {
  643. if (!field.IsRepeated)
  644. {
  645. object unknown;
  646. IEnumLite value = null;
  647. if (input.ReadEnum(ref value, out unknown, field.EnumType))
  648. builder[field] = value;
  649. else if(unknown is int)
  650. MergeVarintField(fieldNumber, (ulong)(int)unknown);
  651. }
  652. else
  653. {
  654. ICollection<object> unknown;
  655. List<IEnumLite> list = new List<IEnumLite>();
  656. input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType);
  657. foreach (IEnumLite en in list)
  658. builder.WeakAddRepeatedField(field, en);
  659. if (unknown != null)
  660. {
  661. foreach (object oval in unknown)
  662. if (oval is int)
  663. MergeVarintField(fieldNumber, (ulong)(int)oval);
  664. }
  665. }
  666. break;
  667. }
  668. default:
  669. {
  670. if (!field.IsRepeated)
  671. {
  672. object value = null;
  673. if (input.ReadPrimitiveField(field.FieldType, ref value))
  674. builder[field] = value;
  675. }
  676. else
  677. {
  678. List<object> list = new List<object>();
  679. input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list);
  680. foreach (object oval in list)
  681. builder.WeakAddRepeatedField(field, oval);
  682. }
  683. break;
  684. }
  685. }
  686. return true;
  687. }
  688. /// <summary>
  689. /// Called by MergeFieldFrom to parse a MessageSet extension.
  690. /// </summary>
  691. private void MergeMessageSetExtensionFromCodedStream(ICodedInputStream input,
  692. ExtensionRegistry extensionRegistry, IBuilder builder)
  693. {
  694. MessageDescriptor type = builder.DescriptorForType;
  695. // The wire format for MessageSet is:
  696. // message MessageSet {
  697. // repeated group Item = 1 {
  698. // required int32 typeId = 2;
  699. // required bytes message = 3;
  700. // }
  701. // }
  702. // "typeId" is the extension's field number. The extension can only be
  703. // a message type, where "message" contains the encoded bytes of that
  704. // message.
  705. //
  706. // In practice, we will probably never see a MessageSet item in which
  707. // the message appears before the type ID, or where either field does not
  708. // appear exactly once. However, in theory such cases are valid, so we
  709. // should be prepared to accept them.
  710. int typeId = 0;
  711. ByteString rawBytes = null; // If we encounter "message" before "typeId"
  712. IBuilderLite subBuilder = null;
  713. FieldDescriptor field = null;
  714. uint lastTag = WireFormat.MessageSetTag.ItemStart;
  715. uint tag;
  716. string name;
  717. while (input.ReadTag(out tag, out name))
  718. {
  719. if (tag == 0)
  720. {
  721. if (input.SkipField())
  722. continue; //can't merge unknown without field tag
  723. break;
  724. }
  725. lastTag = tag;
  726. if (tag == WireFormat.MessageSetTag.TypeID)
  727. {
  728. typeId = 0;
  729. // Zero is not a valid type ID.
  730. if (input.ReadInt32(ref typeId) && typeId != 0)
  731. {
  732. ExtensionInfo extension = extensionRegistry[type, typeId];
  733. if (extension != null)
  734. {
  735. field = extension.Descriptor;
  736. subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
  737. IMessageLite originalMessage = (IMessageLite) builder[field];
  738. if (originalMessage != null)
  739. {
  740. subBuilder.WeakMergeFrom(originalMessage);
  741. }
  742. if (rawBytes != null)
  743. {
  744. // We already encountered the message. Parse it now.
  745. // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
  746. // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
  747. subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
  748. rawBytes = null;
  749. }
  750. }
  751. else
  752. {
  753. // Unknown extension number. If we already saw data, put it
  754. // in rawBytes.
  755. if (rawBytes != null)
  756. {
  757. MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
  758. rawBytes = null;
  759. }
  760. }
  761. }
  762. }
  763. else if (tag == WireFormat.MessageSetTag.Message)
  764. {
  765. if(subBuilder != null)
  766. {
  767. // We already know the type, so we can parse directly from the input
  768. // with no copying. Hooray!
  769. input.ReadMessage(subBuilder, extensionRegistry);
  770. }
  771. else if (input.ReadBytes(ref rawBytes))
  772. {
  773. if (typeId != 0)
  774. {
  775. // We don't know how to parse this. Ignore it.
  776. MergeField(typeId,
  777. UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
  778. }
  779. }
  780. }
  781. else
  782. {
  783. // Unknown tag. Skip it.
  784. if (!input.SkipField())
  785. {
  786. break; // end of group
  787. }
  788. }
  789. }
  790. if (lastTag != WireFormat.MessageSetTag.ItemEnd)
  791. throw InvalidProtocolBufferException.InvalidEndTag();
  792. if (subBuilder != null)
  793. {
  794. builder[field] = subBuilder.WeakBuild();
  795. }
  796. }
  797. #region IBuilderLite Members
  798. bool IBuilderLite.IsInitialized
  799. {
  800. get { return fields != null; }
  801. }
  802. IBuilderLite IBuilderLite.WeakClear()
  803. {
  804. return Clear();
  805. }
  806. IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message)
  807. {
  808. return MergeFrom((UnknownFieldSet) message);
  809. }
  810. IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data)
  811. {
  812. return MergeFrom(data);
  813. }
  814. IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry)
  815. {
  816. return MergeFrom(data);
  817. }
  818. IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input)
  819. {
  820. return MergeFrom(input);
  821. }
  822. IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input, ExtensionRegistry registry)
  823. {
  824. return MergeFrom(input);
  825. }
  826. IMessageLite IBuilderLite.WeakBuild()
  827. {
  828. return Build();
  829. }
  830. IMessageLite IBuilderLite.WeakBuildPartial()
  831. {
  832. return Build();
  833. }
  834. IBuilderLite IBuilderLite.WeakClone()
  835. {
  836. return Build().WeakToBuilder();
  837. }
  838. IMessageLite IBuilderLite.WeakDefaultInstanceForType
  839. {
  840. get { return DefaultInstance; }
  841. }
  842. #endregion
  843. }
  844. }
  845. }