UnknownFieldSet.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://github.com/jskeet/dotnet-protobufs/
  4. // Original C++/Java/Python code:
  5. // http://code.google.com/p/protobuf/
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are
  9. // met:
  10. //
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Google Inc. nor the names of its
  18. // contributors may be used to endorse or promote products derived from
  19. // this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. using System;
  33. using System.Collections.Generic;
  34. using System.IO;
  35. using Google.ProtocolBuffers.Collections;
  36. using Google.ProtocolBuffers.Descriptors;
  37. using Google.ProtocolBuffers.DescriptorProtos;
  38. namespace Google.ProtocolBuffers {
  39. /// <summary>
  40. /// Used to keep track of fields which were seen when parsing a protocol message
  41. /// but whose field numbers or types are unrecognized. This most frequently
  42. /// occurs when new fields are added to a message type and then messages containing
  43. /// those fields are read by old software that was built before the new types were
  44. /// added.
  45. ///
  46. /// Every message contains an UnknownFieldSet.
  47. ///
  48. /// Most users will never need to use this class directly.
  49. /// </summary>
  50. public sealed class UnknownFieldSet {
  51. private static readonly UnknownFieldSet defaultInstance = new UnknownFieldSet(new Dictionary<int, UnknownField>());
  52. private readonly IDictionary<int, UnknownField> fields;
  53. private UnknownFieldSet(IDictionary<int, UnknownField> fields) {
  54. this.fields = fields;
  55. }
  56. /// <summary>
  57. /// Creates a new unknown field set builder.
  58. /// </summary>
  59. public static Builder CreateBuilder() {
  60. return new Builder();
  61. }
  62. /// <summary>
  63. /// Creates a new unknown field set builder
  64. /// and initialize it from <paramref name="original"/>.
  65. /// </summary>
  66. public static Builder CreateBuilder(UnknownFieldSet original) {
  67. return new Builder().MergeFrom(original);
  68. }
  69. public static UnknownFieldSet DefaultInstance {
  70. get { return defaultInstance; }
  71. }
  72. /// <summary>
  73. /// Returns a read-only view of the mapping from field numbers to values.
  74. /// </summary>
  75. public IDictionary<int, UnknownField> FieldDictionary {
  76. get { return Dictionaries.AsReadOnly(fields); }
  77. }
  78. /// <summary>
  79. /// Checks whether or not the given field number is present in the set.
  80. /// </summary>
  81. public bool HasField(int field) {
  82. return fields.ContainsKey(field);
  83. }
  84. /// <summary>
  85. /// Fetches a field by number, returning an empty field if not present.
  86. /// Never returns null.
  87. /// </summary>
  88. public UnknownField this[int number] {
  89. get {
  90. UnknownField ret;
  91. if (!fields.TryGetValue(number, out ret)) {
  92. ret = UnknownField.DefaultInstance;
  93. }
  94. return ret;
  95. }
  96. }
  97. /// <summary>
  98. /// Serializes the set and writes it to <paramref name="output"/>.
  99. /// </summary>
  100. public void WriteTo(CodedOutputStream output) {
  101. foreach (KeyValuePair<int, UnknownField> entry in fields) {
  102. entry.Value.WriteTo(entry.Key, output);
  103. }
  104. }
  105. /// <summary>
  106. /// Gets the number of bytes required to encode this set.
  107. /// </summary>
  108. public int SerializedSize {
  109. get {
  110. int result = 0;
  111. foreach (KeyValuePair<int, UnknownField> entry in fields) {
  112. result += entry.Value.GetSerializedSize(entry.Key);
  113. }
  114. return result;
  115. }
  116. }
  117. /// <summary>
  118. /// Converts the set to a string in protocol buffer text format. This
  119. /// is just a trivial wrapper around TextFormat.PrintToString.
  120. /// </summary>
  121. public override String ToString() {
  122. return TextFormat.PrintToString(this);
  123. }
  124. /// <summary>
  125. /// Serializes the message to a ByteString and returns it. This is
  126. /// just a trivial wrapper around WriteTo(CodedOutputStream).
  127. /// </summary>
  128. /// <returns></returns>
  129. public ByteString ToByteString() {
  130. ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize);
  131. WriteTo(codedBuilder.CodedOutput);
  132. return codedBuilder.Build();
  133. }
  134. /// <summary>
  135. /// Serializes the message to a byte array and returns it. This is
  136. /// just a trivial wrapper around WriteTo(CodedOutputStream).
  137. /// </summary>
  138. /// <returns></returns>
  139. public byte[] ToByteArray() {
  140. byte[] data = new byte[SerializedSize];
  141. CodedOutputStream output = CodedOutputStream.CreateInstance(data);
  142. WriteTo(output);
  143. output.CheckNoSpaceLeft();
  144. return data;
  145. }
  146. /// <summary>
  147. /// Serializes the message and writes it to <paramref name="output"/>. This is
  148. /// just a trivial wrapper around WriteTo(CodedOutputStream).
  149. /// </summary>
  150. /// <param name="output"></param>
  151. public void WriteTo(Stream output) {
  152. CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
  153. WriteTo(codedOutput);
  154. codedOutput.Flush();
  155. }
  156. /// <summary>
  157. /// Serializes the set and writes it to <paramref name="output"/> using
  158. /// the MessageSet wire format.
  159. /// </summary>
  160. public void WriteAsMessageSetTo(CodedOutputStream output) {
  161. foreach (KeyValuePair<int, UnknownField> entry in fields) {
  162. entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output);
  163. }
  164. }
  165. /// <summary>
  166. /// Gets the number of bytes required to encode this set using the MessageSet
  167. /// wire format.
  168. /// </summary>
  169. public int SerializedSizeAsMessageSet {
  170. get {
  171. int result = 0;
  172. foreach (KeyValuePair<int, UnknownField> entry in fields) {
  173. result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key);
  174. }
  175. return result;
  176. }
  177. }
  178. /// <summary>
  179. /// Parses an UnknownFieldSet from the given input.
  180. /// </summary>
  181. public static UnknownFieldSet ParseFrom(CodedInputStream input) {
  182. return CreateBuilder().MergeFrom(input).Build();
  183. }
  184. /// <summary>
  185. /// Parses an UnknownFieldSet from the given data.
  186. /// </summary>
  187. public static UnknownFieldSet ParseFrom(ByteString data) {
  188. return CreateBuilder().MergeFrom(data).Build();
  189. }
  190. /// <summary>
  191. /// Parses an UnknownFieldSet from the given data.
  192. /// </summary>
  193. public static UnknownFieldSet ParseFrom(byte[] data) {
  194. return CreateBuilder().MergeFrom(data).Build();
  195. }
  196. /// <summary>
  197. /// Parses an UnknownFieldSet from the given input.
  198. /// </summary>
  199. public static UnknownFieldSet ParseFrom(Stream input) {
  200. return CreateBuilder().MergeFrom(input).Build();
  201. }
  202. /// <summary>
  203. /// Builder for UnknownFieldSets.
  204. /// </summary>
  205. public sealed class Builder
  206. {
  207. /// <summary>
  208. /// Mapping from number to field. Note that by using a SortedList we ensure
  209. /// that the fields will be serialized in ascending order.
  210. /// </summary>
  211. private IDictionary<int, UnknownField> fields = new SortedList<int, UnknownField>();
  212. // Optimization: We keep around a builder for the last field that was
  213. // modified so that we can efficiently add to it multiple times in a
  214. // row (important when parsing an unknown repeated field).
  215. int lastFieldNumber;
  216. UnknownField.Builder lastField;
  217. internal Builder() {
  218. }
  219. /// <summary>
  220. /// Returns a field builder for the specified field number, including any values
  221. /// which already exist.
  222. /// </summary>
  223. private UnknownField.Builder GetFieldBuilder(int number) {
  224. if (lastField != null) {
  225. if (number == lastFieldNumber) {
  226. return lastField;
  227. }
  228. // Note: AddField() will reset lastField and lastFieldNumber.
  229. AddField(lastFieldNumber, lastField.Build());
  230. }
  231. if (number == 0) {
  232. return null;
  233. }
  234. lastField = UnknownField.CreateBuilder();
  235. UnknownField existing;
  236. if (fields.TryGetValue(number, out existing)) {
  237. lastField.MergeFrom(existing);
  238. }
  239. lastFieldNumber = number;
  240. return lastField;
  241. }
  242. /// <summary>
  243. /// Build the UnknownFieldSet and return it. Once this method has been called,
  244. /// this instance will no longer be usable. Calling any method after this
  245. /// will throw a NullReferenceException.
  246. /// </summary>
  247. public UnknownFieldSet Build() {
  248. GetFieldBuilder(0); // Force lastField to be built.
  249. UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields);
  250. fields = null;
  251. return result;
  252. }
  253. /// <summary>
  254. /// Adds a field to the set. If a field with the same number already exists, it
  255. /// is replaced.
  256. /// </summary>
  257. public Builder AddField(int number, UnknownField field) {
  258. if (number == 0) {
  259. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  260. }
  261. if (lastField != null && lastFieldNumber == number) {
  262. // Discard this.
  263. lastField = null;
  264. lastFieldNumber = 0;
  265. }
  266. fields[number] = field;
  267. return this;
  268. }
  269. /// <summary>
  270. /// Resets the builder to an empty set.
  271. /// </summary>
  272. public Builder Clear() {
  273. fields.Clear();
  274. lastFieldNumber = 0;
  275. lastField = null;
  276. return this;
  277. }
  278. /// <summary>
  279. /// Parse an entire message from <paramref name="input"/> and merge
  280. /// its fields into this set.
  281. /// </summary>
  282. public Builder MergeFrom(CodedInputStream input) {
  283. while (true) {
  284. uint tag = input.ReadTag();
  285. if (tag == 0 || !MergeFieldFrom(tag, input)) {
  286. break;
  287. }
  288. }
  289. return this;
  290. }
  291. /// <summary>
  292. /// Parse a single field from <paramref name="input"/> and merge it
  293. /// into this set.
  294. /// </summary>
  295. /// <param name="tag">The field's tag number, which was already parsed.</param>
  296. /// <param name="input">The coded input stream containing the field</param>
  297. /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
  298. public bool MergeFieldFrom(uint tag, CodedInputStream input) {
  299. int number = WireFormat.GetTagFieldNumber(tag);
  300. switch (WireFormat.GetTagWireType(tag)) {
  301. case WireFormat.WireType.Varint:
  302. GetFieldBuilder(number).AddVarint(input.ReadUInt64());
  303. return true;
  304. case WireFormat.WireType.Fixed64:
  305. GetFieldBuilder(number).AddFixed64(input.ReadFixed64());
  306. return true;
  307. case WireFormat.WireType.LengthDelimited:
  308. GetFieldBuilder(number).AddLengthDelimited(input.ReadBytes());
  309. return true;
  310. case WireFormat.WireType.StartGroup: {
  311. Builder subBuilder = CreateBuilder();
  312. input.ReadUnknownGroup(number, subBuilder);
  313. GetFieldBuilder(number).AddGroup(subBuilder.Build());
  314. return true;
  315. }
  316. case WireFormat.WireType.EndGroup:
  317. return false;
  318. case WireFormat.WireType.Fixed32:
  319. GetFieldBuilder(number).AddFixed32(input.ReadFixed32());
  320. return true;
  321. default:
  322. throw InvalidProtocolBufferException.InvalidWireType();
  323. }
  324. }
  325. /// <summary>
  326. /// Parses <paramref name="input"/> as an UnknownFieldSet and merge it
  327. /// with the set being built. This is just a small wrapper around
  328. /// MergeFrom(CodedInputStream).
  329. /// </summary>
  330. public Builder MergeFrom(Stream input) {
  331. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  332. MergeFrom(codedInput);
  333. codedInput.CheckLastTagWas(0);
  334. return this;
  335. }
  336. /// <summary>
  337. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  338. /// with the set being built. This is just a small wrapper around
  339. /// MergeFrom(CodedInputStream).
  340. /// </summary>
  341. public Builder MergeFrom(ByteString data) {
  342. CodedInputStream input = data.CreateCodedInput();
  343. MergeFrom(input);
  344. input.CheckLastTagWas(0);
  345. return this;
  346. }
  347. /// <summary>
  348. /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it
  349. /// with the set being built. This is just a small wrapper around
  350. /// MergeFrom(CodedInputStream).
  351. /// </summary>
  352. public Builder MergeFrom(byte[] data) {
  353. CodedInputStream input = CodedInputStream.CreateInstance(data);
  354. MergeFrom(input);
  355. input.CheckLastTagWas(0);
  356. return this;
  357. }
  358. /// <summary>
  359. /// Convenience method for merging a new field containing a single varint
  360. /// value. This is used in particular when an unknown enum value is
  361. /// encountered.
  362. /// </summary>
  363. public Builder MergeVarintField(int number, ulong value) {
  364. if (number == 0) {
  365. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  366. }
  367. GetFieldBuilder(number).AddVarint(value);
  368. return this;
  369. }
  370. /// <summary>
  371. /// Merges the fields from <paramref name="other"/> into this set.
  372. /// If a field number exists in both sets, the values in <paramref name="other"/>
  373. /// will be appended to the values in this set.
  374. /// </summary>
  375. public Builder MergeFrom(UnknownFieldSet other) {
  376. if (other != DefaultInstance) {
  377. foreach(KeyValuePair<int, UnknownField> entry in other.fields) {
  378. MergeField(entry.Key, entry.Value);
  379. }
  380. }
  381. return this;
  382. }
  383. /// <summary>
  384. /// Checks if the given field number is present in the set.
  385. /// </summary>
  386. public bool HasField(int number) {
  387. if (number == 0) {
  388. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  389. }
  390. return number == lastFieldNumber || fields.ContainsKey(number);
  391. }
  392. /// <summary>
  393. /// Adds a field to the unknown field set. If a field with the same
  394. /// number already exists, the two are merged.
  395. /// </summary>
  396. public Builder MergeField(int number, UnknownField field) {
  397. if (number == 0) {
  398. throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
  399. }
  400. if (HasField(number)) {
  401. GetFieldBuilder(number).MergeFrom(field);
  402. } else {
  403. // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
  404. // in this case, but that would create a copy of the Field object.
  405. // We'd rather reuse the one passed to us, so call AddField() instead.
  406. AddField(number, field);
  407. }
  408. return this;
  409. }
  410. internal void MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) {
  411. while (true) {
  412. uint tag = input.ReadTag();
  413. if (tag == 0) {
  414. break;
  415. }
  416. if (!MergeFieldFrom(input, extensionRegistry, builder, tag)) {
  417. // end group tag
  418. break;
  419. }
  420. }
  421. }
  422. /// <summary>
  423. /// Like <see cref="MergeFrom(CodedInputStream, ExtensionRegistry, IBuilder)" />
  424. /// but parses a single field.
  425. /// </summary>
  426. /// <param name="input">The input to read the field from</param>
  427. /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param>
  428. /// <param name="builder">Builder to merge field into, if it's a known field</param>
  429. /// <param name="tag">The tag, which should already have been read from the input</param>
  430. /// <returns>true unless the tag is an end-group tag</returns>
  431. internal bool MergeFieldFrom(CodedInputStream input,
  432. ExtensionRegistry extensionRegistry, IBuilder builder, uint tag) {
  433. MessageDescriptor type = builder.DescriptorForType;
  434. if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) {
  435. MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder);
  436. return true;
  437. }
  438. WireFormat.WireType wireType = WireFormat.GetTagWireType(tag);
  439. int fieldNumber = WireFormat.GetTagFieldNumber(tag);
  440. FieldDescriptor field;
  441. IMessage defaultFieldInstance = null;
  442. if (type.IsExtensionNumber(fieldNumber)) {
  443. ExtensionInfo extension = extensionRegistry[type, fieldNumber];
  444. if (extension == null) {
  445. field = null;
  446. } else {
  447. field = extension.Descriptor;
  448. defaultFieldInstance = extension.DefaultInstance;
  449. }
  450. } else {
  451. field = type.FindFieldByNumber(fieldNumber);
  452. }
  453. // Unknown field or wrong wire type. Skip.
  454. if (field == null || wireType != WireFormat.GetWireType(field)) {
  455. return MergeFieldFrom(tag, input);
  456. }
  457. if (field.IsPacked) {
  458. int length = (int)input.ReadRawVarint32();
  459. int limit = input.PushLimit(length);
  460. if (field.FieldType == FieldType.Enum) {
  461. while (!input.ReachedLimit) {
  462. int rawValue = input.ReadEnum();
  463. object value = field.EnumType.FindValueByNumber(rawValue);
  464. if (value == null) {
  465. // If the number isn't recognized as a valid value for this
  466. // enum, drop it (don't even add it to unknownFields).
  467. return true;
  468. }
  469. builder.WeakAddRepeatedField(field, value);
  470. }
  471. } else {
  472. while (!input.ReachedLimit) {
  473. Object value = input.ReadPrimitiveField(field.FieldType);
  474. builder.WeakAddRepeatedField(field, value);
  475. }
  476. }
  477. input.PopLimit(limit);
  478. } else {
  479. object value;
  480. switch (field.FieldType) {
  481. case FieldType.Group:
  482. case FieldType.Message: {
  483. IBuilder subBuilder;
  484. if (defaultFieldInstance != null) {
  485. subBuilder = defaultFieldInstance.WeakCreateBuilderForType();
  486. } else {
  487. subBuilder = builder.CreateBuilderForField(field);
  488. }
  489. if (!field.IsRepeated) {
  490. subBuilder.WeakMergeFrom((IMessage)builder[field]);
  491. }
  492. if (field.FieldType == FieldType.Group) {
  493. input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
  494. } else {
  495. input.ReadMessage(subBuilder, extensionRegistry);
  496. }
  497. value = subBuilder.WeakBuild();
  498. break;
  499. }
  500. case FieldType.Enum: {
  501. int rawValue = input.ReadEnum();
  502. value = field.EnumType.FindValueByNumber(rawValue);
  503. // If the number isn't recognized as a valid value for this enum,
  504. // drop it.
  505. if (value == null) {
  506. MergeVarintField(fieldNumber, (ulong)rawValue);
  507. return true;
  508. }
  509. break;
  510. }
  511. default:
  512. value = input.ReadPrimitiveField(field.FieldType);
  513. break;
  514. }
  515. if (field.IsRepeated) {
  516. builder.WeakAddRepeatedField(field, value);
  517. } else {
  518. builder[field] = value;
  519. }
  520. }
  521. return true;
  522. }
  523. /// <summary>
  524. /// Called by MergeFieldFrom to parse a MessageSet extension.
  525. /// </summary>
  526. private void MergeMessageSetExtensionFromCodedStream(CodedInputStream input,
  527. ExtensionRegistry extensionRegistry, IBuilder builder) {
  528. MessageDescriptor type = builder.DescriptorForType;
  529. // The wire format for MessageSet is:
  530. // message MessageSet {
  531. // repeated group Item = 1 {
  532. // required int32 typeId = 2;
  533. // required bytes message = 3;
  534. // }
  535. // }
  536. // "typeId" is the extension's field number. The extension can only be
  537. // a message type, where "message" contains the encoded bytes of that
  538. // message.
  539. //
  540. // In practice, we will probably never see a MessageSet item in which
  541. // the message appears before the type ID, or where either field does not
  542. // appear exactly once. However, in theory such cases are valid, so we
  543. // should be prepared to accept them.
  544. int typeId = 0;
  545. ByteString rawBytes = null; // If we encounter "message" before "typeId"
  546. IBuilder subBuilder = null;
  547. FieldDescriptor field = null;
  548. while (true) {
  549. uint tag = input.ReadTag();
  550. if (tag == 0) {
  551. break;
  552. }
  553. if (tag == WireFormat.MessageSetTag.TypeID) {
  554. typeId = input.ReadInt32();
  555. // Zero is not a valid type ID.
  556. if (typeId != 0) {
  557. ExtensionInfo extension = extensionRegistry[type, typeId];
  558. if (extension != null) {
  559. field = extension.Descriptor;
  560. subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
  561. IMessage originalMessage = (IMessage)builder[field];
  562. if (originalMessage != null) {
  563. subBuilder.WeakMergeFrom(originalMessage);
  564. }
  565. if (rawBytes != null) {
  566. // We already encountered the message. Parse it now.
  567. // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
  568. // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
  569. subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
  570. rawBytes = null;
  571. }
  572. } else {
  573. // Unknown extension number. If we already saw data, put it
  574. // in rawBytes.
  575. if (rawBytes != null) {
  576. MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
  577. rawBytes = null;
  578. }
  579. }
  580. }
  581. } else if (tag == WireFormat.MessageSetTag.Message) {
  582. if (typeId == 0) {
  583. // We haven't seen a type ID yet, so we have to store the raw bytes for now.
  584. rawBytes = input.ReadBytes();
  585. } else if (subBuilder == null) {
  586. // We don't know how to parse this. Ignore it.
  587. MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(input.ReadBytes()).Build());
  588. } else {
  589. // We already know the type, so we can parse directly from the input
  590. // with no copying. Hooray!
  591. input.ReadMessage(subBuilder, extensionRegistry);
  592. }
  593. } else {
  594. // Unknown tag. Skip it.
  595. if (!input.SkipField(tag)) {
  596. break; // end of group
  597. }
  598. }
  599. }
  600. input.CheckLastTagWas(WireFormat.MessageSetTag.ItemEnd);
  601. if (subBuilder != null) {
  602. builder[field] = subBuilder.WeakBuild();
  603. }
  604. }
  605. }
  606. }
  607. }