UnknownFieldSet.cs 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  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. namespace Google.ProtocolBuffers
  40. {
  41. /// <summary>
  42. /// Used to keep track of fields which were seen when parsing a protocol message
  43. /// but whose field numbers or types are unrecognized. This most frequently
  44. /// occurs when new fields are added to a message type and then messages containing
  45. /// those fields are read by old software that was built before the new types were
  46. /// added.
  47. ///
  48. /// Every message contains an UnknownFieldSet.
  49. ///
  50. /// Most users will never need to use this class directly.
  51. /// </summary>
  52. public sealed partial class UnknownFieldSet : IMessageLite
  53. {
  54. private static readonly UnknownFieldSet defaultInstance =
  55. new UnknownFieldSet(new Dictionary<int, UnknownField>());
  56. private readonly IDictionary<int, UnknownField> fields;
  57. private UnknownFieldSet(IDictionary<int, UnknownField> fields)
  58. {
  59. this.fields = fields;
  60. }
  61. /// <summary>
  62. /// Creates a new unknown field set builder.
  63. /// </summary>
  64. public static Builder CreateBuilder()
  65. {
  66. return new Builder();
  67. }
  68. /// <summary>
  69. /// Creates a new unknown field set builder
  70. /// and initialize it from <paramref name="original"/>.
  71. /// </summary>
  72. public static Builder CreateBuilder(UnknownFieldSet original)
  73. {
  74. return new Builder().MergeFrom(original);
  75. }
  76. public static UnknownFieldSet DefaultInstance
  77. {
  78. get { return defaultInstance; }
  79. }
  80. /// <summary>
  81. /// Returns a read-only view of the mapping from field numbers to values.
  82. /// </summary>
  83. public IDictionary<int, UnknownField> FieldDictionary
  84. {
  85. get { return Dictionaries.AsReadOnly(fields); }
  86. }
  87. /// <summary>
  88. /// Checks whether or not the given field number is present in the set.
  89. /// </summary>
  90. public bool HasField(int field)
  91. {
  92. return fields.ContainsKey(field);
  93. }
  94. /// <summary>
  95. /// Fetches a field by number, returning an empty field if not present.
  96. /// Never returns null.
  97. /// </summary>
  98. public UnknownField this[int number]
  99. {
  100. get
  101. {
  102. UnknownField ret;
  103. if (!fields.TryGetValue(number, out ret))
  104. {
  105. ret = UnknownField.DefaultInstance;
  106. }
  107. return ret;
  108. }
  109. }
  110. /// <summary>
  111. /// Serializes the set and writes it to <paramref name="output"/>.
  112. /// </summary>
  113. public void WriteTo(ICodedOutputStream output)
  114. {
  115. // Avoid creating enumerator for the most common code path.
  116. if (fields.Count > 0)
  117. {
  118. foreach (KeyValuePair<int, UnknownField> entry in fields)
  119. {
  120. entry.Value.WriteTo(entry.Key, output);
  121. }
  122. }
  123. }
  124. /// <summary>
  125. /// Gets the number of bytes required to encode this set.
  126. /// </summary>
  127. public int SerializedSize
  128. {
  129. get
  130. {
  131. // Avoid creating enumerator for the most common code path.
  132. if (fields.Count == 0)
  133. {
  134. return 0;
  135. }
  136. int result = 0;
  137. foreach (KeyValuePair<int, UnknownField> entry in fields)
  138. {
  139. result += entry.Value.GetSerializedSize(entry.Key);
  140. }
  141. return result;
  142. }
  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 override String ToString()
  149. {
  150. return TextFormat.PrintToString(this);
  151. }
  152. /// <summary>
  153. /// Converts the set to a string in protocol buffer text format. This
  154. /// is just a trivial wrapper around TextFormat.PrintToString.
  155. /// </summary>
  156. public void PrintTo(TextWriter writer)
  157. {
  158. TextFormat.Print(this, writer);
  159. }
  160. /// <summary>
  161. /// Serializes the message to a ByteString and returns it. This is
  162. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  163. /// </summary>
  164. /// <returns></returns>
  165. public ByteString ToByteString()
  166. {
  167. ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize);
  168. WriteTo(codedBuilder.CodedOutput);
  169. return codedBuilder.Build();
  170. }
  171. /// <summary>
  172. /// Serializes the message to a byte array and returns it. This is
  173. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  174. /// </summary>
  175. /// <returns></returns>
  176. public byte[] ToByteArray()
  177. {
  178. byte[] data = new byte[SerializedSize];
  179. CodedOutputStream output = CodedOutputStream.CreateInstance(data);
  180. WriteTo(output);
  181. output.CheckNoSpaceLeft();
  182. return data;
  183. }
  184. /// <summary>
  185. /// Serializes the message and writes it to <paramref name="output"/>. This is
  186. /// just a trivial wrapper around WriteTo(ICodedOutputStream).
  187. /// </summary>
  188. /// <param name="output"></param>
  189. public void WriteTo(Stream output)
  190. {
  191. CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
  192. WriteTo(codedOutput);
  193. codedOutput.Flush();
  194. }
  195. /// <summary>
  196. /// Serializes the set and writes it to <paramref name="output"/> using
  197. /// the MessageSet wire format.
  198. /// </summary>
  199. public void WriteAsMessageSetTo(ICodedOutputStream output)
  200. {
  201. // Avoid creating enumerator for the most common code path.
  202. if (fields.Count > 0)
  203. {
  204. foreach (KeyValuePair<int, UnknownField> entry in fields)
  205. {
  206. entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output);
  207. }
  208. }
  209. }
  210. /// <summary>
  211. /// Gets the number of bytes required to encode this set using the MessageSet
  212. /// wire format.
  213. /// </summary>
  214. public int SerializedSizeAsMessageSet
  215. {
  216. get
  217. {
  218. // Avoid creating enumerator for the most common code path.
  219. if (fields.Count == 0)
  220. {
  221. return 0;
  222. }
  223. int result = 0;
  224. foreach (KeyValuePair<int, UnknownField> entry in fields)
  225. {
  226. result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key);
  227. }
  228. return result;
  229. }
  230. }
  231. public override bool Equals(object other)
  232. {
  233. if (ReferenceEquals(this, other))
  234. {
  235. return true;
  236. }
  237. UnknownFieldSet otherSet = other as UnknownFieldSet;
  238. return otherSet != null && Dictionaries.Equals(fields, otherSet.fields);
  239. }
  240. public override int GetHashCode()
  241. {
  242. return Dictionaries.GetHashCode(fields);
  243. }
  244. /// <summary>
  245. /// Parses an UnknownFieldSet from the given input.
  246. /// </summary>
  247. public static UnknownFieldSet ParseFrom(ICodedInputStream input)
  248. {
  249. return CreateBuilder().MergeFrom(input).Build();
  250. }
  251. /// <summary>
  252. /// Parses an UnknownFieldSet from the given data.
  253. /// </summary>
  254. public static UnknownFieldSet ParseFrom(ByteString data)
  255. {
  256. return CreateBuilder().MergeFrom(data).Build();
  257. }
  258. /// <summary>
  259. /// Parses an UnknownFieldSet from the given data.
  260. /// </summary>
  261. public static UnknownFieldSet ParseFrom(byte[] data)
  262. {
  263. return CreateBuilder().MergeFrom(data).Build();
  264. }
  265. /// <summary>
  266. /// Parses an UnknownFieldSet from the given input.
  267. /// </summary>
  268. public static UnknownFieldSet ParseFrom(Stream input)
  269. {
  270. return CreateBuilder().MergeFrom(input).Build();
  271. }
  272. #region IMessageLite Members
  273. public bool IsInitialized
  274. {
  275. get { return fields != null; }
  276. }
  277. public void WriteDelimitedTo(Stream output)
  278. {
  279. CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
  280. codedOutput.WriteRawVarint32((uint) SerializedSize);
  281. WriteTo(codedOutput);
  282. codedOutput.Flush();
  283. }
  284. public IBuilderLite WeakCreateBuilderForType()
  285. {
  286. return new Builder();
  287. }
  288. public IBuilderLite WeakToBuilder()
  289. {
  290. return new Builder(fields);
  291. }
  292. public IMessageLite WeakDefaultInstanceForType
  293. {
  294. get { return defaultInstance; }
  295. }
  296. #endregion
  297. /// <summary>
  298. /// Builder for UnknownFieldSets.
  299. /// </summary>
  300. public sealed partial class Builder : IBuilderLite
  301. {
  302. /// <summary>
  303. /// Mapping from number to field. Note that by using a SortedList we ensure
  304. /// that the fields will be serialized in ascending order.
  305. /// </summary>
  306. private IDictionary<int, UnknownField> fields;
  307. // Optimization: We keep around a builder for the last field that was
  308. // modified so that we can efficiently add to it multiple times in a
  309. // row (important when parsing an unknown repeated field).
  310. private int lastFieldNumber;
  311. private UnknownField.Builder lastField;
  312. internal Builder()
  313. {
  314. fields = new SortedDictionary<int, UnknownField>();
  315. }
  316. internal Builder(IDictionary<int, UnknownField> dictionary)
  317. {
  318. fields = new SortedDictionary<int, UnknownField>(dictionary);
  319. }
  320. /// <summary>
  321. /// Returns a field builder for the specified field number, including any values
  322. /// which already exist.
  323. /// </summary>
  324. private UnknownField.Builder GetFieldBuilder(int number)
  325. {
  326. if (lastField != null)
  327. {
  328. if (number == lastFieldNumber)
  329. {
  330. return lastField;
  331. }
  332. // Note: AddField() will reset lastField and lastFieldNumber.
  333. AddField(lastFieldNumber, lastField.Build());
  334. }
  335. if (number == 0)
  336. {
  337. return null;
  338. }
  339. lastField = UnknownField.CreateBuilder();
  340. UnknownField existing;
  341. if (fields.TryGetValue(number, out existing))
  342. {
  343. lastField.MergeFrom(existing);
  344. }
  345. lastFieldNumber = number;
  346. return lastField;
  347. }
  348. /// <summary>
  349. /// Build the UnknownFieldSet and return it. Once this method has been called,
  350. /// this instance will no longer be usable. Calling any method after this
  351. /// will throw a NullReferenceException.
  352. /// </summary>
  353. public UnknownFieldSet Build()
  354. {
  355. GetFieldBuilder(0); // Force lastField to be built.
  356. UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields);
  357. fields = null;
  358. return result;
  359. }
  360. /// <summary>
  361. /// Adds a field to the set. If a field with the same number already exists, it
  362. /// is replaced.
  363. /// </summary>
  364. public Builder AddField(int number, UnknownField field)
  365. {
  366. if (number == 0)
  367. {
  368. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  369. }
  370. if (lastField != null && lastFieldNumber == number)
  371. {
  372. // Discard this.
  373. lastField = null;
  374. lastFieldNumber = 0;
  375. }
  376. fields[number] = field;
  377. return this;
  378. }
  379. /// <summary>
  380. /// Resets the builder to an empty set.
  381. /// </summary>
  382. public Builder Clear()
  383. {
  384. fields.Clear();
  385. lastFieldNumber = 0;
  386. lastField = null;
  387. return this;
  388. }
  389. /// <summary>
  390. /// Parse an entire message from <paramref name="input"/> and merge
  391. /// its fields into this set.
  392. /// </summary>
  393. public Builder MergeFrom(ICodedInputStream input)
  394. {
  395. uint tag;
  396. string name;
  397. while (input.ReadTag(out tag, out name))
  398. {
  399. if (tag == 0)
  400. {
  401. if (input.SkipField())
  402. {
  403. continue; //can't merge unknown without field tag
  404. }
  405. break;
  406. }
  407. if (!MergeFieldFrom(tag, input))
  408. {
  409. break;
  410. }
  411. }
  412. return this;
  413. }
  414. /// <summary>
  415. /// Parse a single field from <paramref name="input"/> and merge it
  416. /// into this set.
  417. /// </summary>
  418. /// <param name="tag">The field's tag number, which was already parsed.</param>
  419. /// <param name="input">The coded input stream containing the field</param>
  420. /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
  421. public bool MergeFieldFrom(uint tag, ICodedInputStream input)
  422. {
  423. if (tag == 0)
  424. {
  425. input.SkipField();
  426. return true;
  427. }
  428. int number = WireFormat.GetTagFieldNumber(tag);
  429. switch (WireFormat.GetTagWireType(tag))
  430. {
  431. case WireFormat.WireType.Varint:
  432. {
  433. ulong uint64 = 0;
  434. if (input.ReadUInt64(ref uint64))
  435. {
  436. GetFieldBuilder(number).AddVarint(uint64);
  437. }
  438. return true;
  439. }
  440. case WireFormat.WireType.Fixed32:
  441. {
  442. uint uint32 = 0;
  443. if (input.ReadFixed32(ref uint32))
  444. {
  445. GetFieldBuilder(number).AddFixed32(uint32);
  446. }
  447. return true;
  448. }
  449. case WireFormat.WireType.Fixed64:
  450. {
  451. ulong uint64 = 0;
  452. if (input.ReadFixed64(ref uint64))
  453. {
  454. GetFieldBuilder(number).AddFixed64(uint64);
  455. }
  456. return true;
  457. }
  458. case WireFormat.WireType.LengthDelimited:
  459. {
  460. ByteString bytes = null;
  461. if (input.ReadBytes(ref bytes))
  462. {
  463. GetFieldBuilder(number).AddLengthDelimited(bytes);
  464. }
  465. return true;
  466. }
  467. case WireFormat.WireType.StartGroup:
  468. {
  469. Builder subBuilder = CreateBuilder();
  470. #pragma warning disable 0612
  471. input.ReadUnknownGroup(number, subBuilder);
  472. #pragma warning restore 0612
  473. GetFieldBuilder(number).AddGroup(subBuilder.Build());
  474. return true;
  475. }
  476. case WireFormat.WireType.EndGroup:
  477. return false;
  478. default:
  479. throw InvalidProtocolBufferException.InvalidWireType();
  480. }
  481. }
  482. /// <summary>
  483. /// Parses <paramref name="input"/> as an UnknownFieldSet and merge it
  484. /// with the set being built. This is just a small wrapper around
  485. /// MergeFrom(ICodedInputStream).
  486. /// </summary>
  487. public Builder MergeFrom(Stream input)
  488. {
  489. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  490. MergeFrom(codedInput);
  491. codedInput.CheckLastTagWas(0);
  492. return this;
  493. }
  494. /// <summary>
  495. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  496. /// with the set being built. This is just a small wrapper around
  497. /// MergeFrom(ICodedInputStream).
  498. /// </summary>
  499. public Builder MergeFrom(ByteString data)
  500. {
  501. CodedInputStream input = data.CreateCodedInput();
  502. MergeFrom(input);
  503. input.CheckLastTagWas(0);
  504. return this;
  505. }
  506. /// <summary>
  507. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  508. /// with the set being built. This is just a small wrapper around
  509. /// MergeFrom(ICodedInputStream).
  510. /// </summary>
  511. public Builder MergeFrom(byte[] data)
  512. {
  513. CodedInputStream input = CodedInputStream.CreateInstance(data);
  514. MergeFrom(input);
  515. input.CheckLastTagWas(0);
  516. return this;
  517. }
  518. /// <summary>
  519. /// Convenience method for merging a new field containing a single varint
  520. /// value. This is used in particular when an unknown enum value is
  521. /// encountered.
  522. /// </summary>
  523. public Builder MergeVarintField(int number, ulong value)
  524. {
  525. if (number == 0)
  526. {
  527. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  528. }
  529. GetFieldBuilder(number).AddVarint(value);
  530. return this;
  531. }
  532. /// <summary>
  533. /// Merges the fields from <paramref name="other"/> into this set.
  534. /// If a field number exists in both sets, the values in <paramref name="other"/>
  535. /// will be appended to the values in this set.
  536. /// </summary>
  537. public Builder MergeFrom(UnknownFieldSet other)
  538. {
  539. if (other != DefaultInstance)
  540. {
  541. foreach (KeyValuePair<int, UnknownField> entry in other.fields)
  542. {
  543. MergeField(entry.Key, entry.Value);
  544. }
  545. }
  546. return this;
  547. }
  548. /// <summary>
  549. /// Checks if the given field number is present in the set.
  550. /// </summary>
  551. public bool HasField(int number)
  552. {
  553. if (number == 0)
  554. {
  555. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  556. }
  557. return number == lastFieldNumber || fields.ContainsKey(number);
  558. }
  559. /// <summary>
  560. /// Adds a field to the unknown field set. If a field with the same
  561. /// number already exists, the two are merged.
  562. /// </summary>
  563. public Builder MergeField(int number, UnknownField field)
  564. {
  565. if (number == 0)
  566. {
  567. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  568. }
  569. if (HasField(number))
  570. {
  571. GetFieldBuilder(number).MergeFrom(field);
  572. }
  573. else
  574. {
  575. // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
  576. // in this case, but that would create a copy of the Field object.
  577. // We'd rather reuse the one passed to us, so call AddField() instead.
  578. AddField(number, field);
  579. }
  580. return this;
  581. }
  582. internal void MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder)
  583. {
  584. uint tag;
  585. string name;
  586. while (input.ReadTag(out tag, out name))
  587. {
  588. if (tag == 0 && name != null)
  589. {
  590. FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(name);
  591. if (fieldByName != null)
  592. {
  593. tag = WireFormat.MakeTag(fieldByName);
  594. }
  595. else
  596. {
  597. ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, name);
  598. if (extension != null)
  599. {
  600. tag = WireFormat.MakeTag(extension.Descriptor);
  601. }
  602. }
  603. }
  604. if (tag == 0)
  605. {
  606. if (input.SkipField())
  607. {
  608. continue; //can't merge unknown without field tag
  609. }
  610. break;
  611. }
  612. if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name))
  613. {
  614. // end group tag
  615. break;
  616. }
  617. }
  618. }
  619. /// <summary>
  620. /// Like <see cref="MergeFrom(ICodedInputStream, ExtensionRegistry, IBuilder)" />
  621. /// but parses a single field.
  622. /// </summary>
  623. /// <param name="input">The input to read the field from</param>
  624. /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param>
  625. /// <param name="builder">Builder to merge field into, if it's a known field</param>
  626. /// <param name="tag">The tag, which should already have been read from the input</param>
  627. /// <returns>true unless the tag is an end-group tag</returns>
  628. internal bool MergeFieldFrom(ICodedInputStream input,
  629. ExtensionRegistry extensionRegistry, IBuilder builder, uint tag,
  630. string fieldName)
  631. {
  632. if (tag == 0 && fieldName != null)
  633. {
  634. FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(fieldName);
  635. if (fieldByName != null)
  636. {
  637. tag = WireFormat.MakeTag(fieldByName);
  638. }
  639. else
  640. {
  641. ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, fieldName);
  642. if (extension != null)
  643. {
  644. tag = WireFormat.MakeTag(extension.Descriptor);
  645. }
  646. }
  647. }
  648. MessageDescriptor type = builder.DescriptorForType;
  649. if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart)
  650. {
  651. MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder);
  652. return true;
  653. }
  654. WireFormat.WireType wireType = WireFormat.GetTagWireType(tag);
  655. int fieldNumber = WireFormat.GetTagFieldNumber(tag);
  656. FieldDescriptor field;
  657. IMessageLite defaultFieldInstance = null;
  658. if (type.IsExtensionNumber(fieldNumber))
  659. {
  660. ExtensionInfo extension = extensionRegistry[type, fieldNumber];
  661. if (extension == null)
  662. {
  663. field = null;
  664. }
  665. else
  666. {
  667. field = extension.Descriptor;
  668. defaultFieldInstance = extension.DefaultInstance;
  669. }
  670. }
  671. else
  672. {
  673. field = type.FindFieldByNumber(fieldNumber);
  674. }
  675. // Unknown field or wrong wire type. Skip.
  676. if (field == null)
  677. {
  678. return MergeFieldFrom(tag, input);
  679. }
  680. if (wireType != WireFormat.GetWireType(field))
  681. {
  682. WireFormat.WireType expectedType = WireFormat.GetWireType(field.FieldType);
  683. if (wireType == expectedType)
  684. {
  685. //Allowed as of 2.3, this is unpacked data for a packed array
  686. }
  687. else if (field.IsRepeated && wireType == WireFormat.WireType.LengthDelimited &&
  688. (expectedType == WireFormat.WireType.Varint || expectedType == WireFormat.WireType.Fixed32 ||
  689. expectedType == WireFormat.WireType.Fixed64))
  690. {
  691. //Allowed as of 2.3, this is packed data for an unpacked array
  692. }
  693. else
  694. {
  695. return MergeFieldFrom(tag, input);
  696. }
  697. }
  698. switch (field.FieldType)
  699. {
  700. case FieldType.Group:
  701. case FieldType.Message:
  702. {
  703. IBuilderLite subBuilder = (defaultFieldInstance != null)
  704. ? defaultFieldInstance.WeakCreateBuilderForType()
  705. : builder.CreateBuilderForField(field);
  706. if (!field.IsRepeated)
  707. {
  708. subBuilder.WeakMergeFrom((IMessageLite) builder[field]);
  709. if (field.FieldType == FieldType.Group)
  710. {
  711. input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
  712. }
  713. else
  714. {
  715. input.ReadMessage(subBuilder, extensionRegistry);
  716. }
  717. builder[field] = subBuilder.WeakBuild();
  718. }
  719. else
  720. {
  721. List<IMessageLite> list = new List<IMessageLite>();
  722. if (field.FieldType == FieldType.Group)
  723. {
  724. input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType,
  725. extensionRegistry);
  726. }
  727. else
  728. {
  729. input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType,
  730. extensionRegistry);
  731. }
  732. foreach (IMessageLite m in list)
  733. {
  734. builder.WeakAddRepeatedField(field, m);
  735. }
  736. return true;
  737. }
  738. break;
  739. }
  740. case FieldType.Enum:
  741. {
  742. if (!field.IsRepeated)
  743. {
  744. object unknown;
  745. IEnumLite value = null;
  746. if (input.ReadEnum(ref value, out unknown, field.EnumType))
  747. {
  748. builder[field] = value;
  749. }
  750. else if (unknown is int)
  751. {
  752. MergeVarintField(fieldNumber, (ulong) (int) unknown);
  753. }
  754. }
  755. else
  756. {
  757. ICollection<object> unknown;
  758. List<IEnumLite> list = new List<IEnumLite>();
  759. input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType);
  760. foreach (IEnumLite en in list)
  761. {
  762. builder.WeakAddRepeatedField(field, en);
  763. }
  764. if (unknown != null)
  765. {
  766. foreach (object oval in unknown)
  767. {
  768. if (oval is int)
  769. {
  770. MergeVarintField(fieldNumber, (ulong) (int) oval);
  771. }
  772. }
  773. }
  774. }
  775. break;
  776. }
  777. default:
  778. {
  779. if (!field.IsRepeated)
  780. {
  781. object value = null;
  782. if (input.ReadPrimitiveField(field.FieldType, ref value))
  783. {
  784. builder[field] = value;
  785. }
  786. }
  787. else
  788. {
  789. List<object> list = new List<object>();
  790. input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list);
  791. foreach (object oval in list)
  792. {
  793. builder.WeakAddRepeatedField(field, oval);
  794. }
  795. }
  796. break;
  797. }
  798. }
  799. return true;
  800. }
  801. /// <summary>
  802. /// Called by MergeFieldFrom to parse a MessageSet extension.
  803. /// </summary>
  804. private void MergeMessageSetExtensionFromCodedStream(ICodedInputStream input,
  805. ExtensionRegistry extensionRegistry, IBuilder builder)
  806. {
  807. MessageDescriptor type = builder.DescriptorForType;
  808. // The wire format for MessageSet is:
  809. // message MessageSet {
  810. // repeated group Item = 1 {
  811. // required int32 typeId = 2;
  812. // required bytes message = 3;
  813. // }
  814. // }
  815. // "typeId" is the extension's field number. The extension can only be
  816. // a message type, where "message" contains the encoded bytes of that
  817. // message.
  818. //
  819. // In practice, we will probably never see a MessageSet item in which
  820. // the message appears before the type ID, or where either field does not
  821. // appear exactly once. However, in theory such cases are valid, so we
  822. // should be prepared to accept them.
  823. int typeId = 0;
  824. ByteString rawBytes = null; // If we encounter "message" before "typeId"
  825. IBuilderLite subBuilder = null;
  826. FieldDescriptor field = null;
  827. uint lastTag = WireFormat.MessageSetTag.ItemStart;
  828. uint tag;
  829. string name;
  830. while (input.ReadTag(out tag, out name))
  831. {
  832. if (tag == 0 && name != null)
  833. {
  834. if (name == "type_id")
  835. {
  836. tag = WireFormat.MessageSetTag.TypeID;
  837. }
  838. else if (name == "message")
  839. {
  840. tag = WireFormat.MessageSetTag.Message;
  841. }
  842. }
  843. if (tag == 0)
  844. {
  845. if (input.SkipField())
  846. {
  847. continue; //can't merge unknown without field tag
  848. }
  849. break;
  850. }
  851. lastTag = tag;
  852. if (tag == WireFormat.MessageSetTag.TypeID)
  853. {
  854. typeId = 0;
  855. // Zero is not a valid type ID.
  856. if (input.ReadInt32(ref typeId) && typeId != 0)
  857. {
  858. ExtensionInfo extension = extensionRegistry[type, typeId];
  859. if (extension != null)
  860. {
  861. field = extension.Descriptor;
  862. subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
  863. IMessageLite originalMessage = (IMessageLite) builder[field];
  864. if (originalMessage != null)
  865. {
  866. subBuilder.WeakMergeFrom(originalMessage);
  867. }
  868. if (rawBytes != null)
  869. {
  870. // We already encountered the message. Parse it now.
  871. // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
  872. // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
  873. subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
  874. rawBytes = null;
  875. }
  876. }
  877. else
  878. {
  879. // Unknown extension number. If we already saw data, put it
  880. // in rawBytes.
  881. if (rawBytes != null)
  882. {
  883. MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
  884. rawBytes = null;
  885. }
  886. }
  887. }
  888. }
  889. else if (tag == WireFormat.MessageSetTag.Message)
  890. {
  891. if (subBuilder != null)
  892. {
  893. // We already know the type, so we can parse directly from the input
  894. // with no copying. Hooray!
  895. input.ReadMessage(subBuilder, extensionRegistry);
  896. }
  897. else if (input.ReadBytes(ref rawBytes))
  898. {
  899. if (typeId != 0)
  900. {
  901. // We don't know how to parse this. Ignore it.
  902. MergeField(typeId,
  903. UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
  904. }
  905. }
  906. }
  907. else
  908. {
  909. // Unknown tag. Skip it.
  910. if (!input.SkipField())
  911. {
  912. break; // end of group
  913. }
  914. }
  915. }
  916. if (lastTag != WireFormat.MessageSetTag.ItemEnd)
  917. {
  918. throw InvalidProtocolBufferException.InvalidEndTag();
  919. }
  920. if (subBuilder != null)
  921. {
  922. builder[field] = subBuilder.WeakBuild();
  923. }
  924. }
  925. #region IBuilderLite Members
  926. bool IBuilderLite.IsInitialized
  927. {
  928. get { return fields != null; }
  929. }
  930. IBuilderLite IBuilderLite.WeakClear()
  931. {
  932. return Clear();
  933. }
  934. IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message)
  935. {
  936. return MergeFrom((UnknownFieldSet) message);
  937. }
  938. IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data)
  939. {
  940. return MergeFrom(data);
  941. }
  942. IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry)
  943. {
  944. return MergeFrom(data);
  945. }
  946. IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input)
  947. {
  948. return MergeFrom(input);
  949. }
  950. IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input, ExtensionRegistry registry)
  951. {
  952. return MergeFrom(input);
  953. }
  954. IMessageLite IBuilderLite.WeakBuild()
  955. {
  956. return Build();
  957. }
  958. IMessageLite IBuilderLite.WeakBuildPartial()
  959. {
  960. return Build();
  961. }
  962. IBuilderLite IBuilderLite.WeakClone()
  963. {
  964. return Build().WeakToBuilder();
  965. }
  966. IMessageLite IBuilderLite.WeakDefaultInstanceForType
  967. {
  968. get { return DefaultInstance; }
  969. }
  970. #endregion
  971. }
  972. }
  973. }